diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..c54ec58 --- /dev/null +++ b/todo.md @@ -0,0 +1,404 @@ +# saQut Compiler Toolbox — Yol Haritası ve Yapılacaklar + +> **Felsefe**: saQut bir derleyici değil, bir **derleyici alet çantasıdır**. +> Amacı en hızlı kodu üretmek, en güvenli sandbox'u kurmak veya en optimize +> binary'yi çıkarmak değildir. Amacı, **derleyicinin kendisidir**. +> +> Her aşama (Lexer, Parser, Optimizer, Compiler) birbirinden bağımsız, +> kendi parametreleriyle yönlendirilebilen, gerektiğinde devre dışı +> bırakılabilen birer **araç kutusu modülü** olarak tasarlanır. +> +> Geliştirici, isterse sadece token listesini alır, isterse AST'yi JSON +> olarak çeker, isterse sembol tablosunu inceler, isterse kodu çalıştırır. +> Bu, ileride LSP sunucusu yazmayı, IDE eklentileri geliştirmeyi ve +> kod hiyerarşisi görselleştirmeyi mümkün kılar. + +--- + +## Temel Prensipler + +1. **Her aşama bağımsız**: Lexer → Tokenizer → Parser → Optimizer → IR → Backend. + Her biri tek başına çalışabilir, kendi parametrelerini alır. + +2. **Her şey metadata**: Her token ve AST düğümü; dosya adı, satır, sütun, + karakter offset'i taşır. Debug ve hata mesajları bu veri üzerine kurulur. + +3. **AST bellek canavarı**: Token'lar AST'de yaşar. Kaynak kodun neredeyse + birebir izdüşümü AST üzerinde korunur. Hiçbir bilgi atılmaz. + +4. **Sembol tablosu aynı felsefede**: Basit yapı, çok veri. Her sembolün + tanımlandığı yer, tipi, kullanıldığı tüm noktalar, scope bilgisi. + +5. **Feature toggle**: Her keyword, her operatör, her optimizasyon adımı + açılıp kapatılabilir. `--disable-while`, `--skip-constant-folding`. + +6. **Çoklu çıktı formatı**: Düz metin, JSON, (ileride) HTML/SVG. Tüm ara + gösterimler dışa aktarılabilir. + +7. **IR merkezli backend**: Tüm backend'ler (C transpile, QBE, LLVM, JIT) + aynı IR'den beslenir. Yeni backend eklemek = yeni bir IR yürüteci yazmak. + +--- + +## Aşama 0: Metadata ve Konum Takibi + +> **Hedef**: Her token ve AST düğümü nereden geldiğini bilsin. + +### 0.1 SourceFile Yöneticisi +- [ ] `SourceFile` sınıfı: dosya adı, tam metin, satır başı offset'leri +- [ ] `SourceLocation` yapısı: `{file, line, column, offset}` +- [ ] `offset → (line, column)` dönüşümü (binary search ile O(log n)) +- [ ] Çoklu dosya desteği (import/include için temel) + +### 0.2 Lexer'a Konum Ekleme +- [ ] Lexer her `nextChar()`'da satır/sütun takibi yapsın +- [ ] `getLocation()` → mevcut konumu `SourceLocation` olarak döndürsün +- [ ] `INumber` yapısına `SourceLocation startLoc, endLoc` eklensin + +### 0.3 Token'lara Konum Ekleme +- [ ] `Token` temel sınıfına `SourceLocation loc` eklensin +- [ ] Her token oluşturulurken konumu kaydedilsin +- [ ] `start`/`end` offset'leri `SourceLocation` ile değiştirilsin + +### 0.4 AST Düğümlerine Konum Ekleme +- [ ] `ASTNode` temel sınıfına `SourceLocation loc` eklensin +- [ ] Her düğüm oluşturulurken ilgili token'ın konumu kopyalansın + +--- + +## Aşama 1: Interpreter (CLI + Dosya) + +> **Hedef**: `saqut` komutu ile REPL veya dosya çalıştırma. + +### 1.1 CLI Altyapısı +- [ ] `argc/argv` ile komut satırı argümanları +- [ ] `./saqut` → REPL modu (etkileşimli) +- [ ] `./saqut file.sqt` → dosyayı çalıştır +- [ ] `./saqut --mode=parse file.sqt` → sadece AST üret +- [ ] `./saqut --mode=tokens file.sqt` → sadece token listesi +- [ ] `./saqut --mode=ir file.sqt` → sadece IR +- [ ] `./saqut --mode=symbols file.sqt` → sembol tablosu +- [ ] `./saqut --format=json file.sqt` → JSON çıktı + +### 1.2 REPL Modu +- [ ] `>` komut istemi +- [ ] Her satır ayrı ayrı parse edilir +- [ ] `.ast` komutu → son ifadenin AST'sini göster +- [ ] `.tokens` komutu → son ifadenin token'larını göster +- [ ] `.symbols` komutu → şu ana kadarki sembolleri göster +- [ ] `.exit` / `.quit` → çıkış +- [ ] Çok satırlı giriş (bloklar için) + +### 1.3 Dosya Modu +- [ ] Kaynak dosyayı oku → pipeline'ı çalıştır +- [ ] Çıktıyı seçilen formatta bas +- [ ] `-o output.json` → dosyaya yaz + +--- + +## Aşama 2: AST'yi Bellek Canavarı Yapma + +> **Hedef**: AST, kaynak kodun tam bir izdüşümü olsun. +> Hiçbir bilgi kaybolmasın. Token'lar AST'de yaşasın. + +### 2.1 Token Tutma +- [ ] AST düğümleri token'ları **sahiplensin** (unique_ptr veya shared_ptr) +- [ ] `LiteralNode`, `IdentifierNode` → ilgili token'ı doğrudan tutar +- [ ] `BinaryExpressionNode` → operatör token'ını tutar +- [ ] Her statement → ilgili keyword token'ını tutar (`if` token'ı, `for` token'ı) + +### 2.2 Kaynak Kod Parçası Erişimi +- [ ] `ASTNode::getSourceText()` → bu düğümün kaynak koddaki ham metni +- [ ] `ASTNode::getSourceRange()` → başlangıç/bitiş SourceLocation +- [ ] Hata mesajlarında kaynak kod parçası gösterimi: + ``` + Hata: test.sqt:5:10: 'x' değişkeni tanımlı değil + 4 | int main() { + 5 | y = x + 1; + | ^ + 6 | } + ``` + +### 2.3 AST Görselleştirme +- [ ] `--format=json` → tam AST'yi JSON olarak dök +- [ ] `--format=dot` → Graphviz DOT formatı (görsel ağaç) +- [ ] `--format=html` → Etkileşimli HTML ağaç görünümü (ileride) +- [ ] JSON çıktısı her düğüm için: + ```json + { + "kind": "BinaryExpression", + "operator": "PLUS", + "location": { "file": "test.sqt", "line": 5, "column": 9 }, + "sourceText": "x + 1", + "left": { ... }, + "right": { ... } + } + ``` + +--- + +## Aşama 3: Sembol Tablosu + +> **Hedef**: AST kadar zengin, basit yapılı bir sembol tablosu. +> Her sembolün tüm kullanım noktaları, tip bilgisi, scope'u kayıtlı. + +### 3.1 Symbol Sınıfı +- [ ] `Symbol` yapısı: + - `name`: sembol adı + - `kind`: variable, function, parameter, type, ... + - `type`: tip bilgisi (şimdilik string, ileride Type sistemi) + - `definitionLoc`: tanımlandığı SourceLocation + - `references`: kullanıldığı tüm SourceLocation'ların listesi + - `scope`: ait olduğu scope (global, function, block) + - `metadata`: opsiyonel anahtar-değer çiftleri + +### 3.2 SymbolTable Sınıfı +- [ ] İç içe scope desteği (global → function → block) +- [ ] `enterScope()` / `exitScope()` +- [ ] `define(name, kind, type, location)` → yeni sembol ekle +- [ ] `resolve(name)` → en yakın scope'tan başlayarak ara +- [ ] `addReference(name, location)` → kullanım noktası ekle +- [ ] `getAllSymbols()` → tüm scope'lardaki tüm semboller (düz liste) +- [ ] JSON'a serialize edilebilme + +### 3.3 Sembol Toplama (AST Walker) +- [ ] `SymbolCollector` sınıfı: AST'yi dolaşır, sembolleri toplar +- [ ] Değişken tanımlarını yakala → `define()` +- [ ] Değişken kullanımlarını yakala → `addReference()` +- [ ] Fonksiyon tanımlarını yakala +- [ ] Hata durumları: tanımsız değişken, çift tanım, tip uyuşmazlığı + +--- + +## Aşama 4: Feature Toggle Sistemi + +> **Hedef**: Derleyicinin her özelliği açılıp kapatılabilir olsun. + +### 4.1 CompilerConfig Yapısı +- [ ] `CompilerConfig` struct'ı: + ```cpp + struct CompilerConfig { + // Dil özellikleri + bool enableWhile = true; + bool enableFor = true; + bool enableDoWhile = true; + bool enableSwitch = true; + bool enableClass = false; // henüz yok + bool enableInterface = false; + bool enableEnum = false; + + // Operatörler + bool enableTernary = true; + bool enablePostfix = true; + bool enableUnary = true; + + // Optimizasyon adımları + bool optConstantFolding = false; + bool optDeadCodeElim = false; + bool optUnusedVariable = false; + + // Çıktı + std::string outputFormat = "text"; // text, json + std::string mode = "run"; // tokens, ast, ir, symbols, run + std::string inputFile; + std::string outputFile; + }; + ``` + +### 4.2 Keyword Kontrolü +- [ ] Tokenizer, config'te kapalı keyword'leri identifier olarak tanısın +- [ ] Parser, kapalı keyword'ler için hata değil, görmezden gelsin +- [ ] `--disable-while` → `while` artık bir keyword değil + +### 4.3 Optimizasyon Kontrolü +- [ ] Her optimizasyon adımı bir `OptimizationPass` soyut sınıfı +- [ ] `OptimizationManager`: config'e göre pas'ları çalıştırır +- [ ] `--skip-constant-folding` → o adım atlanır +- [ ] `--opt-all` → tüm optimizasyonlar aktif +- [ ] `--opt-none` → hiçbiri aktif değil + +--- + +## Aşama 5: Çoklu Backend Altyapısı (IR Merkezli) + +> **Hedef**: Tüm backend'ler aynı IR'den beslenir. +> Yeni backend eklemek = yeni bir `IRRunner` yazmak. + +### 5.1 IR'yi Güçlendirme +- [ ] Kontrol akışı: `br`, `jmp`, `cmp`, `br_eq`, `br_lt`, `br_gt` +- [ ] Fonksiyon: `call`, `ret`, `param` +- [ ] Bellek: `load`, `store`, `alloca` +- [ ] Tip bilgisi: her IR komutu tipleri taşısın +- [ ] Debug bilgisi: kaynak satır eşlemesi +- [ ] `IRModule` sınıfı: fonksiyon listesi, global değişkenler, IR komutları + +### 5.2 Backend Arayüzü +- [ ] `IBackend` soyut sınıfı: + ```cpp + class IBackend { + public: + virtual bool initialize(CompilerConfig& config) = 0; + virtual bool compile(IRModule& ir) = 0; + virtual bool run() = 0; + virtual std::string getOutput() = 0; + virtual ~IBackend() = default; + }; + ``` + +### 5.3 C Transpile Backend (Aşama 1) +- [ ] IR → C kaynak kodu dönüşümü +- [ ] Değişken tanımları, if/for/while, fonksiyonlar +- [ ] GCC/Clang ile derleme ve çalıştırma +- [ ] Üretilen C kodu okunabilir ve debug edilebilir olmalı + +### 5.4 Interpreter Backend (Aşama 1) +- [ ] IR'yi doğrudan yürüten sanal makine +- [ ] Stack tabanlı veya register tabanlı +- [ ] Adım adım çalıştırma (step) desteği +- [ ] Değişken değerlerini gösterme + +### 5.5 QBE Backend (Aşama 2) +- [ ] QBE C API'si ile entegrasyon +- [ ] IR → QBE IR dönüşümü +- [ ] Native binary üretimi + +### 5.6 LLVM Backend (Aşama 3, opsiyonel) +- [ ] LLVM C API ile entegrasyon +- [ ] IR → LLVM IR dönüşümü +- [ ] Agresif optimizasyonlar, çok platformlu kod üretimi + +--- + +## Aşama 6: Hata Sistemi + +> **Hedef**: Sadece hata mesajı değil, **açıklama**. +> Kullanıcıya neyi yanlış yaptığını ve nasıl düzelteceğini söyle. + +### 6.1 Diagnostic Sistemi +- [ ] `Diagnostic` yapısı: `{level, location, message, hint, sourceLine}` +- [ ] Seviyeler: error, warning, note, hint +- [ ] Birden fazla diagnostic toplama (ilk hatada durma) +- [ ] `DiagnosticEngine`: diagnostic'leri toplar, formatlar, basar + +### 6.2 Hata Mesajı Formatı +- [ ] Kaynak satır gösterimi (^^^^ işaretleme) +- [ ] Renkli çıktı (opsiyonel, `--color`) +- [ ] JSON formatında da alınabilir +- [ ] Hata kodları (örn: E0001, W0002) + +### 6.3 Zengin Hata Açıklamaları +- [ ] Tanımsız değişken → "x tanımlı değil. Bunu mu demek istediniz: xy?" +- [ ] Tip uyuşmazlığı → "int bekleniyor ama float verilmiş. Cast ekleyin." +- [ ] Eksik noktalı virgül → "; eksik. Bu satırın sonuna ekleyin." +- [ ] Sembol tablosu kullanarak bağlamlı öneriler + +--- + +## Aşama 7: LSP Sunucusu (Uzun Vade) + +> **Hedef**: VS Code ve diğer IDE'ler için tam dil desteği. +> Tüm metadata ve çoklu çıktı formatları LSP'yi kolaylaştırır. + +### 7.1 LSP Protokolü Temelleri +- [ ] `initialize`, `shutdown`, `exit` +- [ ] `textDocument/didOpen`, `didChange`, `didClose` +- [ ] JSON-RPC 2.0 üzerinden iletişim + +### 7.2 Dil Özellikleri +- [ ] **Syntax highlighting**: Token listesini LSP'e bildir +- [ ] **Diagnostics**: Hata/uyarıları anlık bildir +- [ ] **Go to definition**: Sembol tablosundan tanım konumuna git +- [ ] **Find references**: Sembolün tüm kullanım noktalarını bul +- [ ] **Hover**: İmleç üstündeki sembol hakkında bilgi göster +- [ ] **Code completion**: Bağlama göre öneriler (sembol tablosundan) +- [ ] **Document symbols**: Dosyadaki tüm sembolleri listele (AST'den) +- [ ] **Code lens**: Fonksiyon başına reference sayısı + +### 7.3 Kod Hiyerarşisi Görselleştirme +- [ ] `--format=html` ile etkileşimli AST ağacı +- [ ] AST'yi JSON olarak alıp web UI'da görselleştirme +- [ ] Sembol tablosunu grafik olarak gösterme +- [ ] Fonksiyon çağrı grafiği (call graph) + +--- + +## Aşama 8: Test ve Kalite + +### 8.1 Birim Testleri +- [ ] Lexer testleri: her sayı formatı, her operatör, string +- [ ] Tokenizer testleri: keyword'ler, delimiter'lar, yorumlar +- [ ] Parser testleri: her statement tipi, iç içe ifadeler, hata durumları +- [ ] IR testleri: her opcode, doğru register tahsisi +- [ ] Sembol tablosu testleri: tanımlama, çözümleme, scope + +### 8.2 Anlık Görüntü (Snapshot) Testleri +- [ ] `source.sqt` → `output.json` karşılaştırması +- [ ] Her commit'te AST/IR/sembol çıktısı değişmemeli (regresyon) + +### 8.3 Benchmark +- [ ] Büyük dosya parse süresi +- [ ] Tokenizer throughput (token/saniye) +- [ ] Bellek kullanımı + +--- + +## Öncelik Sıralaması + +``` +Şu an (Aşama 0) ──▶ Metadata ve konum takibi + │ +Haftaya (Aşama 1) ──▶ CLI + REPL + dosya modu + │ +2 hafta (Aşama 2) ──▶ Bellek canavarı AST + JSON çıktı + │ +3 hafta (Aşama 3) ──▶ Sembol tablosu + │ +4 hafta (Aşama 4) ──▶ Feature toggle + CompilerConfig + │ +5 hafta (Aşama 5) ──▶ IR güçlendirme + C transpile backend + │ +6 hafta (Aşama 6) ──▶ Diagnostic + zengin hata mesajları + │ +... (Aşama 7-8) ──▶ LSP, testler, benchmark +``` + +--- + +## Anlık Görevler (Bu Hafta) + +### Bugün / Yarın +- [ ] `SourceLocation` yapısını tanımla (`src/core/location.hpp`) +- [ ] `SourceFile` sınıfını yaz (offset → satır/sütun dönüşümü) +- [ ] Lexer'a satır/sütun takibi ekle +- [ ] `INumber` yerine `SourceLocation` kullanan yeni yapı + +### Bu Hafta +- [ ] Token'lara `SourceLocation` ekle +- [ ] AST düğümlerine `SourceLocation` ekle +- [ ] Token'ları AST'nin sahiplenmesi (unique_ptr) +- [ ] CLI modülü: argc/argv, temel komutlar + +--- + +## Mimari Notlar + +### Neden Bellek Canavarı? +Çünkü amaç **bilgiyi korumak**. Derleyiciler genelde parse ettikten sonra +kaynak kod bilgisini atar. Biz atmayacağız. Bu sayede: +- Hata mesajlarında kaynak kodu gösterebiliriz +- IDE'de "go to definition" yapabiliriz +- Kodu yeniden oluşturabiliriz (pretty printer) +- Dönüşümleri (refactoring) güvenle yapabiliriz + +### Neden Feature Toggle? +Çünkü bu bir **toolbox**. Kullanıcı dili özelleştirebilmeli: +- Eğitim amaçlı: önce sadece if/else, sonra while ekle +- Deney amaçlı: "while olmadan program yazabilir misin?" +- Güvenlik: belirli yapıları yasakla (eval, system call) +- DSL: kendi alt-dilini oluştur + +### Neden IR Merkezli? +IR, tüm backend'lerin ortak dilidir. Yeni bir backend eklemek +istediğimizde parser'ı, lexer'ı, optimizer'ı değiştirmemize gerek kalmaz. +Sadece IR → Hedef dönüşümü yazarız. Bu, LLVM dışında QBE, Cranelift, +hatta kendi JIT'imizi eklemeyi mümkün kılar.