docs: belgeleri yeniden hizala (IR+VM modeli, kilitli kararlar)
- Calistirma modeli: "JIT" terimi birakildi -> IR + bytecode VM birincil; makine-kodu JIT kapsam disi (ADR-015). C-transpile ikinci backend. - readme.md bastan yazildi: toolbox cercevesi, yapilan vs planlanan ayrimi. - ADR amend: 007 (klon yuk tasir), 009 (fixpoint degismezi + analiz yeniden hesabi), 010 (literal baglama-gore tipleme), 011 (global baslatici uc-parcali kural + dongusel struct E010), 014 (bellek gerekcesi). - Yeni ADR: 015 (IR+VM), 016 (FFI seam), 017 (batteries=sinir), 018 (interface ertelendi), 019 (frontend<->runtime ayrimi). - roadmap: bu hafta sembol tablosu->fibonacci; once dikey dilim; E010. - examples: Final.sqt -> parser-stress/ (gecersiz fixture); yeni gecerli fibonacci.sqt eklendi. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f7467f18b3
commit
cf6f706449
|
|
@ -9,6 +9,13 @@
|
||||||
> Bu kararlar bir tasarım oturumunda (kullanıcı + asistan) tartışılarak alındı.
|
> Bu kararlar bir tasarım oturumunda (kullanıcı + asistan) tartışılarak alındı.
|
||||||
> Tartışmanın tam akışı için bkz. `docs/transkript-frontend-tasarim.md`.
|
> Tartışmanın tam akışı için bkz. `docs/transkript-frontend-tasarim.md`.
|
||||||
> Uygulama planı için bkz. `docs/roadmap-frontend.md`.
|
> Uygulama planı için bkz. `docs/roadmap-frontend.md`.
|
||||||
|
>
|
||||||
|
> ⚠️ **Yapılan vs planlanan:** Bu belgedeki ADR-006…019 **tasarım kararlarıdır**;
|
||||||
|
> tarif edilen makine (sembol tablosu, semantik analiz, tip sistemi, diagnostic,
|
||||||
|
> optimizasyon, IR+VM) **henüz kodlanmamıştır.** Bugün çalışan: lexer, tokenizer,
|
||||||
|
> Pratt parser, AST, AST'nin JSON serileştirmesi, CLI iskeleti, konum takibi ve
|
||||||
|
> basit aritmetiği düşüren minimal bir IR deneyi. Hiçbir ADR, var olmayan bir
|
||||||
|
> mekanizmayı varmış gibi anlatmaz.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -48,10 +55,10 @@ mimarisi):
|
||||||
```
|
```
|
||||||
FRONTEND MIDDLE-END BACKEND
|
FRONTEND MIDDLE-END BACKEND
|
||||||
lexer → token → optimizasyon IR lowering →
|
lexer → token → optimizasyon IR lowering →
|
||||||
parser → AST → (opsiyonel, iteratif, kod üretimi
|
parser → AST → (opsiyonel, iteratif, bytecode VM (birincil)
|
||||||
symbol table → toggle'lı, ortak (C transpile /
|
symbol table → toggle'lı, ortak + ileride C transpile
|
||||||
semantic analiz gösterim üstünde) QBE / JIT)
|
semantic analiz gösterim üstünde) (makine kodu = uzak
|
||||||
(annotated AST)
|
(annotated AST) gelecek; ADR-015)
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Pass 1 (Syntax):** token → ham AST. (Büyük ölçüde mevcut.)
|
- **Pass 1 (Syntax):** token → ham AST. (Büyük ölçüde mevcut.)
|
||||||
|
|
@ -62,9 +69,10 @@ semantic analiz gösterim üstünde) QBE / JIT)
|
||||||
"Parser ve symbol hikayesini bitirmek" = **frontend'i bitirmek.** Optimizasyon
|
"Parser ve symbol hikayesini bitirmek" = **frontend'i bitirmek.** Optimizasyon
|
||||||
ayrı bir katmandır (middle-end), backend'ler bu ortak çıktıdan beslenir.
|
ayrı bir katmandır (middle-end), backend'ler bu ortak çıktıdan beslenir.
|
||||||
|
|
||||||
**Neden bu katmanlama?** Birden çok backend (C transpile, QBE, JIT) planlandığı
|
**Neden bu katmanlama?** Birden çok backend (birincil: IR+bytecode VM, ADR-015;
|
||||||
için, ortak işler (analiz, optimizasyon) **bir kez** ortak katmanda yapılmalı;
|
ileride: C transpile; çok uzak: makine kodu) hedeflendiği için, ortak işler
|
||||||
yoksa her backend aynı optimizasyonu yeniden yazar.
|
(analiz, optimizasyon) **bir kez** ortak katmanda yapılmalı; yoksa her backend
|
||||||
|
aynı optimizasyonu yeniden yazar.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -109,6 +117,35 @@ saqut ast file.sqt → ham + annotate edilmiş AST (1+2 burada duru
|
||||||
saqut ast file.sqt --optimized → klon, folding uygulanmış (3 var)
|
saqut ast file.sqt --optimized → klon, folding uygulanmış (3 var)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Güncelleme — Klon maliyeti yük taşır (load-bearing)
|
||||||
|
|
||||||
|
İlk metin "ağaç klonlamak ucuz ve basittir" diyordu; bu **klon maliyetini hafife
|
||||||
|
alıyor** ve bir **tutarlılık (coherence) problemini** atlıyordu. Düzeltme:
|
||||||
|
|
||||||
|
`ASTNode::clone()` "belki gerekir" değil, **merkezi ve spesifiye edilmesi
|
||||||
|
zorunlu** bir bileşendir; tüm öncesi/sonrası hikâyesi ona dayanır (bkz. roadmap
|
||||||
|
Faz 4'te clone() yükseltildi).
|
||||||
|
|
||||||
|
**Klonlanırken karar verilmesi gereken iki nokta (açıkça belgele):**
|
||||||
|
|
||||||
|
1. **Parent pointer'lar yeniden bağlanmalı.** Klon node'larının `parent`'ı
|
||||||
|
orijinali değil, klonu göstermeli; yoksa yapısal doğrulama ve dönüşümler
|
||||||
|
yanlış ağaçta gezinir.
|
||||||
|
|
||||||
|
2. **`IdentifierNode → Symbol` bağları: paylaş mı, yeniden eşle mi?**
|
||||||
|
- **Paylaş** (klon ve orijinal aynı sembol tablosuna işaret eder): ucuz, ama
|
||||||
|
klonu optimize etmek orijinalin **referans sayımlarını bozar** (DCE klonda
|
||||||
|
bir kullanımı silince orijinalin Symbol ref-count'u da düşer).
|
||||||
|
- **Yeniden eşle** (klona ait bir sembol tablosu kopyası): doğru, ama ucuz
|
||||||
|
değil.
|
||||||
|
- **Karar:** `--optimized` istendiğinde sembol tablosu da **klonlanır ve
|
||||||
|
yeniden eşlenir** (remap). Doğruluk, ucuzluğa tercih edilir; klon zaten
|
||||||
|
yalnızca optimizasyon istendiğinde üretilir, sıcak yol değildir. "Ucuz"
|
||||||
|
iddiası kaldırıldı.
|
||||||
|
|
||||||
|
Bu, ADR-013'teki "ref-count Symbol'da yaşar" kararıyla tutarlıdır: ref-count
|
||||||
|
Symbol'da olduğu için, klonun kendi Symbol'larına sahip olması şarttır.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ADR-008: Optimizasyon Konumu — AST mı, IR mı?
|
## ADR-008: Optimizasyon Konumu — AST mı, IR mı?
|
||||||
|
|
@ -129,7 +166,7 @@ sorusu tartışıldı. İki uç yaklaşım var:
|
||||||
- **Kaynak-seviyesi, ağaç-yerel optimizasyonlar** (constant folding, ölü kod
|
- **Kaynak-seviyesi, ağaç-yerel optimizasyonlar** (constant folding, ölü kod
|
||||||
işaretleme, unused variable) → **AST'de** yapılır. Çünkü:
|
işaretleme, unused variable) → **AST'de** yapılır. Çünkü:
|
||||||
1. Dil JS gibi basit; ağır optimizasyona ihtiyaç yok.
|
1. Dil JS gibi basit; ağır optimizasyona ihtiyaç yok.
|
||||||
2. Backend-bağımsız → C transpile, QBE, JIT üçü birden faydalanır.
|
2. Backend-bağımsız → bytecode VM ve ileride C transpile birden faydalanır.
|
||||||
3. İncelenebilir kalır (`saqut ast --optimized`) — projenin varlık sebebi.
|
3. İncelenebilir kalır (`saqut ast --optimized`) — projenin varlık sebebi.
|
||||||
|
|
||||||
- **CFG/dataflow gerektiren optimizasyonlar** ("bir kez atanıp bir kez
|
- **CFG/dataflow gerektiren optimizasyonlar** ("bir kez atanıp bir kez
|
||||||
|
|
@ -169,6 +206,39 @@ belki 7 — kodun kendisi belirler.
|
||||||
> her **tur** daha az değişiklik yapar. Analiz pass'leri (symbol table, type check)
|
> her **tur** daha az değişiklik yapar. Analiz pass'leri (symbol table, type check)
|
||||||
> "kolaylaşmaz"; onlar bir kez çalışır.
|
> "kolaylaşmaz"; onlar bir kez çalışır.
|
||||||
|
|
||||||
|
### Güncelleme — Sonlanma değişmezi (termination invariant)
|
||||||
|
|
||||||
|
Fixpoint döngüsünün **sonlanacağı garanti edilmeli**. İki seçenekten en az biri
|
||||||
|
zorunludur:
|
||||||
|
|
||||||
|
1. **Monotonluk:** havuzdaki tüm pass'ler **monoton** olmalı — yalnızca
|
||||||
|
küçültür/sadeleştirir, asla büyütmez. Constant folding ve dead code
|
||||||
|
elimination bugün monotondur, dolayısıyla fixpoint sonlanır.
|
||||||
|
2. **Sert iterasyon tavanı (cap):** bir üst sınır (örn. `maxFixpointRounds`).
|
||||||
|
|
||||||
|
**Neden gerekli:** ileride **büyüten** pass'ler (inlining, loop unrolling)
|
||||||
|
eklenirse, naif fixpoint **salınabilir** (A büyütür, B küçültür, sonsuz döngü).
|
||||||
|
Büyüten bir pass eklendiği an, monotonluk bozulur ve **iterasyon tavanı zorunlu
|
||||||
|
hale gelir.** Bu değişmez şimdiden yazıya geçirildi ki ileride unutulmasın.
|
||||||
|
|
||||||
|
### Güncelleme — "Analiz bir kez çalışır" çelişkisinin çözümü
|
||||||
|
|
||||||
|
ADR-013 "analiz bir kez çalışır" diyor; ama folding **erişilebilirliği**
|
||||||
|
(`if(false)`) ve **referans sayımlarını** değiştirir, DCE de tam bunlara
|
||||||
|
dayanır. Eğer analiz gerçekten yalnızca bir kez çalışırsa, fixpoint'in ikinci
|
||||||
|
turundaki DCE **bayat (stale) veriyle** çalışır ve zincirleme fırsatları kaçırır.
|
||||||
|
|
||||||
|
**Çözüm — iki analiz sınıfını ayır:**
|
||||||
|
|
||||||
|
- **Kaynağa-bağlı analiz** (her ifadenin tipi, sembol bağları): kaynak değişmediği
|
||||||
|
sürece sabittir → **bir kez** çalışır, klona taşınır.
|
||||||
|
- **Türetilmiş/akışa-bağlı analiz** (erişilebilirlik `isReachable`, referans
|
||||||
|
sayıları): bir dönüşüm bunları geçersizleştirir → **fixpoint döngüsünün her
|
||||||
|
turunda, klon üzerinde yeniden hesaplanır.**
|
||||||
|
|
||||||
|
Yani "analiz bir kez çalışır" ifadesi yalnızca **kaynağa-bağlı** analiz için
|
||||||
|
geçerlidir; akışa-bağlı analiz tur başına tazelenir. ADR-013 buna göre okunmalı.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ADR-010: Tip Sistemi Tasarımı
|
## ADR-010: Tip Sistemi Tasarımı
|
||||||
|
|
@ -205,6 +275,33 @@ boyut tip eşitliğine girmez (JS gibi). Tip kontrolü basit kalır.
|
||||||
de olabilir, yıllarca repolarda tozlanabilir de." Temel sağlam ve büyümeye açık
|
de olabilir, yıllarca repolarda tozlanabilir de." Temel sağlam ve büyümeye açık
|
||||||
olmalı.
|
olmalı.
|
||||||
|
|
||||||
|
### Güncelleme — Sayısal literal tipleme kuralı
|
||||||
|
|
||||||
|
"Gizli dönüşüm yok + tip çıkarımı yok" altında `float x = 1;` ifadesi
|
||||||
|
**tanımsızdı**. Bu açıkça karara bağlanmalı, çünkü tip denetleyicisini (Faz 3)
|
||||||
|
doğrudan yönlendirir.
|
||||||
|
|
||||||
|
**Değerlendirilen iki kural:**
|
||||||
|
|
||||||
|
- **(a) Literal her zaman `int`:** `1` daima `int`'tir. `float x = 1;` bir tip
|
||||||
|
hatasıdır; `float x = 1.0;` yazmak zorunludur. En katı, en öngörülebilir; ama
|
||||||
|
rahatsız edici ve "gizli dönüşüm yok" ilkesini literallere kadar gereksiz yere
|
||||||
|
zorlar.
|
||||||
|
- **(b) Tamsayı literali bağlama-göre tiplenir (context-typed / polymorphic):**
|
||||||
|
tipsiz bir tamsayı sabiti, beklenen tip ona **kayıpsız** sığıyorsa o tipe
|
||||||
|
uyarlanır. `float x = 1;` çalışır (`1` → `1.0`); `int y = 1.5;` ise hata
|
||||||
|
(kayıp olur).
|
||||||
|
|
||||||
|
**Karar:** ✅ **(b) Bağlama-göre tiplenen tamsayı literalleri.**
|
||||||
|
|
||||||
|
- Gerekçe: bu bir **değişken-değer dönüşümü değil, bir derleme-zamanı sabitinin
|
||||||
|
uygun tipte yorumlanmasıdır** — tam olarak ADR-010'un zaten tanıdığı "sabit
|
||||||
|
istisnası" (`int a = 5/2 → 2`) ruhuyla aynı kapıya çıkar. Çalışma zamanı
|
||||||
|
`int` değişkenini `float`'a gizlice çevirmek hâlâ **yasaktır**; istisna
|
||||||
|
yalnızca **literal/sabit** içindir.
|
||||||
|
- Kural net: *değişken→değişken* gizli dönüşüm yok; *literal→beklenen tip*
|
||||||
|
kayıpsızsa serbest. `float x = anInt;` hata; `float x = 1;` serbest.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ADR-011: Scope ve Forward Reference Kuralları
|
## ADR-011: Scope ve Forward Reference Kuralları
|
||||||
|
|
@ -269,6 +366,44 @@ Her katman bir namespace tutar; değişken bulunamazsa bir üst katmanda aranır
|
||||||
derdi yalnızca global'ler içindir, onu da Geçiş 1 çözer (global'ler en baştan
|
derdi yalnızca global'ler içindir, onu da Geçiş 1 çözer (global'ler en baştan
|
||||||
tamamen doludur).
|
tamamen doludur).
|
||||||
|
|
||||||
|
### Güncelleme — Global "tam forward reference" çok genişti: üç-parçalı kural
|
||||||
|
|
||||||
|
İlk metin "global = her zaman forward-reference güvenli" diyordu; bu **fazla
|
||||||
|
geniş**. Global bir değişkenin **başlatıcısının (initializer) bir çalışma
|
||||||
|
sırası vardır** (tıpkı lokaller gibi). Düzeltme — üç ayrı kural:
|
||||||
|
|
||||||
|
1. **Global fonksiyonlar / struct'lar → tam hoisting.** Tanım anında çalışmazlar,
|
||||||
|
sıradan bağımsız her yerde görünür. (Güvenli; değişmedi.)
|
||||||
|
2. **Global değişken isimleri → hoist edilir.** İsim her yerde görünür.
|
||||||
|
3. **Global değişken başlatıcıları → değer sırasına tabidir** (lokaller gibi) →
|
||||||
|
**declare-before-use** VEYA bir **definite-assignment (kesin-atama) analizi**
|
||||||
|
gerektirir.
|
||||||
|
|
||||||
|
**Neden:** `int a = b; int b = 5;` global scope'ta, isim-hoisting'e güvenilirse,
|
||||||
|
`a`'ya **sessizce çöp değer** verir — kaçınmaya çalıştığımız tam o JS `var`
|
||||||
|
durumu. Java da aynı sebeple bunu kısıtlar. Karar: global başlatıcılar için de
|
||||||
|
**declare-before-use** uygulanır (en basit, definite-assignment'a gerek
|
||||||
|
bırakmaz). Yani isim görünür ama **kendinden önceki** bir global başlatıcıda
|
||||||
|
kullanılabilir.
|
||||||
|
|
||||||
|
### Güncelleme — Döngüsel / karşılıklı-özyinelemeli struct tespiti
|
||||||
|
|
||||||
|
Pointer olmadığı için tüm struct iç içeliği **değer (by-value)** ile olur →
|
||||||
|
herhangi bir kapsama döngüsü sonsuz boyut demektir:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct A { B b } // A, B'yi değer olarak içerir
|
||||||
|
struct B { A a } // B, A'yı değer olarak içerir → sonsuz boyut
|
||||||
|
```
|
||||||
|
|
||||||
|
Bu **derleme hatası olmak zorunda** ve hata kataloğunda **eksikti**. Eklendi:
|
||||||
|
**`E010` — özyinelemeli/döngüsel struct tanımı.** Symbol toplama sonrası bir
|
||||||
|
**topolojik / kapsama-döngüsü kontrolü** çalışır (struct'ları düğüm, "alan
|
||||||
|
olarak içerir" kenarını çevrim arayan bir DFS ile). Çevrim bulunursa `E010`.
|
||||||
|
|
||||||
|
(Karşılaştır: `struct A { B b }` + `struct B { int x }` geçerlidir; yalnızca
|
||||||
|
**çevrim** yasaktır. Pointer olsaydı çevrim mümkün olurdu — ama pointer yok.)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ADR-012: ExpressionNode / StatementNode Ara Tabanları
|
## ADR-012: ExpressionNode / StatementNode Ara Tabanları
|
||||||
|
|
@ -351,12 +486,14 @@ Sebep: kullanım sayısı **değişkene** aittir, tek bir kullanım node'una de
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Pointer (kullanıcı syntax'ı `*`/`&`) | ❌ Yok | Ama derleyici/runtime **içeride** pointer'ı sonuna kadar kullanır |
|
| Pointer (kullanıcı syntax'ı `*`/`&`) | ❌ Yok | Ama derleyici/runtime **içeride** pointer'ı sonuna kadar kullanır |
|
||||||
| Tuple / Generic (`<T,U>`) | ❌ Yok | |
|
| Tuple / Generic (`<T,U>`) | ❌ Yok | |
|
||||||
| Class / OOP | ❌ Yok (başta) | `class` keyword'ü yok sayılır |
|
| Class / OOP / kalıtım | ❌ Yok (başta) | `class` keyword'ü yok sayılır |
|
||||||
| Struct | ✅ Var | `struct A { B bVar }` olur (B başka yerde tanımlı); recursive define yok |
|
| Closure | ❌ Yok | Bkz. ADR-019 (bellek bağımlılığı) |
|
||||||
|
| Struct | ✅ Var | `struct A { B bVar }` olur (B başka yerde tanımlı); **çevrim yasak → `E010`** |
|
||||||
|
| `interface` | ⏸️ Ertelendi | Reddedilmedi; v0 değil — gerekçe aşağıda + ADR-018 |
|
||||||
| Array | ✅ `int[]` | Dinamik yönde; runtime bellek modeli ertelendi |
|
| Array | ✅ `int[]` | Dinamik yönde; runtime bellek modeli ertelendi |
|
||||||
| Fonksiyonlar | ✅ Tipli | Dönüş + parametre tipleri zorunlu |
|
| Fonksiyonlar | ✅ Tipli | Dönüş + parametre tipleri zorunlu |
|
||||||
| `auto` / tip çıkarımı | ❌ Yok | Her şey açık tipli |
|
| `auto` / tip çıkarımı | ❌ Yok | Her şey açık tipli |
|
||||||
| Gizli int↔float dönüşümü | ❌ Yok | Sadece sabit folding'de istisna |
|
| Gizli int↔float dönüşümü | ❌ Yok | Sadece sabit/literal folding'de istisna (ADR-010) |
|
||||||
|
|
||||||
### Dinamik Array'in Bellek Yükümlülüğü (Gelecek Notu)
|
### Dinamik Array'in Bellek Yükümlülüğü (Gelecek Notu)
|
||||||
|
|
||||||
|
|
@ -364,13 +501,164 @@ Sebep: kullanım sayısı **değişkene** aittir, tek bir kullanım node'una de
|
||||||
bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır:
|
bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır:
|
||||||
|
|
||||||
- **Frontend:** yalnızca "bu int dizisi" bilgisini ister; bellek modelinden habersiz.
|
- **Frontend:** yalnızca "bu int dizisi" bilgisini ister; bellek modelinden habersiz.
|
||||||
- **C transpile backend (ilk backend):** `int[]` → C'de `struct {int* data; size_t len, cap;}`,
|
- **IR + bytecode VM (ilk çalıştırma modeli, ADR-015):** bellek host (C++)
|
||||||
`malloc/realloc/free` ile yönetilir. Bellek yönetimi C'den hazır gelir.
|
heap'idir; array'ler host tarafında `std::vector` benzeri bir yapıyla tutulur.
|
||||||
- **JIT backend:** bellek yönetimini kendi yapmaz; minik bir runtime kütüphanesi
|
VM, array işlemleri için **host fonksiyonlarına** (FFI seam, ADR-016) çağrı
|
||||||
(`array_new`, `array_push`, `array_free`) olur, JIT bunlara **call** emit eder.
|
yapar. v0 için özel allocator gerekmez.
|
||||||
- **Yönetim stratejisi (ne zaman free):** en basiti scope-tabanlı ownership
|
- **C transpile backend (ileride, ikinci backend):** `int[]` → C'de
|
||||||
(array'i tutan değişken scope'tan çıkınca free). GC gerekmez. Runtime'a
|
`struct {int* data; size_t len, cap;}`, `malloc/realloc/free` ile yönetilir.
|
||||||
gelince kararlaştırılır.
|
- **Yönetim stratejisi (ne zaman free):** scope-tabanlı ownership (array'i tutan
|
||||||
|
değişken scope'tan çıkınca free). GC gerekmez — **neden gerekmediği aşağıda
|
||||||
|
gerekçelendirildi.**
|
||||||
|
|
||||||
|
### Güncelleme — Scope-tabanlı bellek artık GEREKÇELİ (bağımlılığı belgele)
|
||||||
|
|
||||||
|
Önceki kaygı ("scope çıkışında free, aliasing/escape altında bozulur") kilitli
|
||||||
|
dil kimliğiyle **lehte çözüldü:**
|
||||||
|
|
||||||
|
> prosedürel + value semantics + kullanıcı pointer'ı yok + closure yok + kaçan
|
||||||
|
> referans yok → array/string'ler tanımlandıkları scope'tan **kaçamaz** →
|
||||||
|
> scope-tabanlı ownership (scope çıkışında free) **gerçekten çalışır, GC
|
||||||
|
> gerekmez.**
|
||||||
|
|
||||||
|
**Bağımlılık açıkça yazılır:** scope-tabanlı bellek, *yalnızca* no-pointer /
|
||||||
|
value-semantics seçimi sayesinde geçerlidir. `interface` değerleri veya kaçan
|
||||||
|
referanslar eklenirse bu sorun **yeniden açılır**. (Bu, `interface`'i ertelemenin
|
||||||
|
ikinci sebebidir — bkz. ADR-018, ADR-019.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-015: Çalıştırma Modeli — IR + Bytecode VM (Makine-Kodu JIT Kapsam Dışı)
|
||||||
|
|
||||||
|
### Bağlam
|
||||||
|
|
||||||
|
Daha önceki belge/konuşmalarda çalıştırma için "JIT" terimi geçiyordu. Hangi
|
||||||
|
çalıştırma modeli? Üç uç var: tree-walker, bytecode VM, gerçek makine-kodu JIT.
|
||||||
|
|
||||||
|
### Değerlendirilen Yaklaşımlar
|
||||||
|
|
||||||
|
- **Tree-walker (AST'yi doğrudan gez-çalıştır):** en basit, ama **çok yavaş**;
|
||||||
|
her çalıştırmada ağaç gezilir.
|
||||||
|
- **Makine-kodu JIT** (register allocation, ABI/çağırma sözleşmeleri,
|
||||||
|
çalıştırılabilir `mmap` bellek): en hızlı; ama **tek faydası ham hızdır**, ki
|
||||||
|
burada öncelik değil. Determinizmi ve incelenebilirliği zorlaştırır, devasa
|
||||||
|
mühendislik yükü getirir.
|
||||||
|
- **IR + bytecode VM** (kendi IR'imize derle, yorumlayıcı döngü ile çalıştır):
|
||||||
|
determinizm ve incelenebilirliği **doğrudan** sağlar; tree-walker'dan hızlı;
|
||||||
|
bellek host heap'iyle kolay.
|
||||||
|
|
||||||
|
### Karar
|
||||||
|
|
||||||
|
✅ **IR + bytecode VM.** saQut kendi IR'sine derler ve bir yorumlayıcı döngüyle
|
||||||
|
çalıştırır.
|
||||||
|
|
||||||
|
- ❌ **Makine-kodu JIT kapsam dışıdır** (terminoloji düzeltmesi: "JIT" demeyi
|
||||||
|
bırak). Öncelikler **determinizm + incelenebilirlik** (toolbox), ham hız değil.
|
||||||
|
- **Bellek kolaydır:** host (C++) heap'i; özel runtime allocator yok (v0).
|
||||||
|
- **C'ye transpile, geçerli bir İKİNCİ backend olarak ileride kalır** (frontend
|
||||||
|
backend-bağımsız, ADR-006).
|
||||||
|
- İleride makine kodu **gerçekten** istenirse: elle code generator yazmak yerine
|
||||||
|
**libgccjit / LLVM'e bağlan** (ADR-001'deki QBE/custom değerlendirmeleri o gün
|
||||||
|
için geçerli). Bu **çok uzak gelecektir.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-016: FFI Seam — Host Fonksiyon Çağırma Deliği
|
||||||
|
|
||||||
|
### Bağlam
|
||||||
|
|
||||||
|
`print` bile bir "dış dünya" çağrısıdır; VM tek başına ekrana yazamaz, host'tan
|
||||||
|
bir fonksiyon çağırmalıdır. Bu ihtiyaç ya **kaza eseri** tek bir özel-durum
|
||||||
|
olarak gömülür, ya da **kasıtlı bir mekanizma** olarak tasarlanır.
|
||||||
|
|
||||||
|
### Karar
|
||||||
|
|
||||||
|
✅ **IR/runtime tasarımına bilinçli bir FFI seam konur:** "host fonksiyonu çağır"
|
||||||
|
için tek, genel bir IR mekanizması (örn. `callhost <id>, args...`).
|
||||||
|
|
||||||
|
- `print` bu seam'in **ilk müşterisidir**, özel-durum değil.
|
||||||
|
- İleride tüm "batteries" (bkz. ADR-017) bu sınır üzerinden gelir: sıkıştırma/
|
||||||
|
kripto C kütüphaneleri buraya bağlanır.
|
||||||
|
- **Neden şimdi:** seam'i sonradan eklemek IR ve VM'i baştan değiştirmeyi
|
||||||
|
gerektirir; deliği bir kez doğru açmak ucuzdur. Mekanizmayı **şimdi** doğru
|
||||||
|
tasarla, içini sonra doldur.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-017: Batteries / Stdlib — Sınır Problemi (Ertelendi)
|
||||||
|
|
||||||
|
### Bağlam
|
||||||
|
|
||||||
|
Gerçek bir genel sürüm pil ile gelmeli (sıralama, sıkıştırma, kripto,
|
||||||
|
JSON/XML/HTML, ileride runtime/donanım, ses/görüntü/video). JSON/string
|
||||||
|
ergonomisi olmayan bir dil benimsenmez — bu doğru. Ama korku: pilleri çekirdeğe
|
||||||
|
gömmek **monolit** yaratır.
|
||||||
|
|
||||||
|
### Karar
|
||||||
|
|
||||||
|
✅ **Pil = sınır (boundary) problemi, "zlib'i yeniden yaz" problemi değil.**
|
||||||
|
|
||||||
|
- Çekirdek: **küçük bir gerçek builtin kümesi** (`print`, temel zorunlular) +
|
||||||
|
**gerisi kütüphane/FFI.**
|
||||||
|
- **JSON/XML/HTML ayrıştırıcıları saQut'ta yazılabilir** (string + struct +
|
||||||
|
fonksiyon + kontrol akışı yeter) — ilk "gerçek program" demoları.
|
||||||
|
- **Sıkıştırma/kripto:** denenmiş C kütüphanelerine **FFI** ile bağlan. **Kripto
|
||||||
|
asla elle yazılmaz.**
|
||||||
|
- **Bugüne tek yansıması:** FFI seam'i (ADR-016) bırak. Gerisi **v0 kapsamı
|
||||||
|
dışıdır.** Sınır bir kez çizilir, piller üstünde sonsuza dek birikir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-018: `interface` Ertelemesi (Reddedilmedi)
|
||||||
|
|
||||||
|
### Bağlam
|
||||||
|
|
||||||
|
Kullanıcı struct'ın yanında `interface` de istedi (crypto, compression, custom
|
||||||
|
data types, JSON, string için). `interface` alınmalı mı, ne zaman?
|
||||||
|
|
||||||
|
### Karar
|
||||||
|
|
||||||
|
✅ **Şimdi `struct`, `interface` ise ertelenir (reddedilmez).**
|
||||||
|
|
||||||
|
**Neden ertelendi:** `interface`, `struct`'tan kategorik olarak ağırdır.
|
||||||
|
- Struct yalnızca alan yerleşimidir (field layout).
|
||||||
|
- Interface "bu metotları sağlayan herhangi bir tip" demektir → çağrı yerinde
|
||||||
|
somut tip **bilinmez** → **dinamik dispatch** → vtable / fat pointer (içsel
|
||||||
|
pointer, izinli) → ve bir interface değeri **herhangi bir tipi tutabilir**, bu
|
||||||
|
da **kaçma/yaşam-süresi (escape/lifetime) problemini yeniden açar** (ADR-019).
|
||||||
|
- Go bunu fat pointer + GC ile çözer; saQut **GC istemiyor.**
|
||||||
|
|
||||||
|
Kullanıcının saydığı her şey (crypto, compression, custom data, JSON, string)
|
||||||
|
**yalnızca struct + fonksiyonla** yapılabilir (C bunu kanıtlar). Dolayısıyla:
|
||||||
|
şimdi struct'ı al, interface'i ertele.
|
||||||
|
|
||||||
|
**Metot-çağrı şekeri** (`list.push(5)` → `push(list, 5)`) ileride **parser
|
||||||
|
seviyesinde, sıfır semantik maliyetli** bir desugaring olarak eklenebilir —
|
||||||
|
şimdi değil.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-019: Frontend ↔ Runtime Sorumluluk Ayrımı
|
||||||
|
|
||||||
|
### Bağlam
|
||||||
|
|
||||||
|
"Hangi CPU çekirdeği, hangi cihaz, ne zaman tetiklenir, hangi çıktı formatı"
|
||||||
|
gibi sorular nereye ait? Frontend'e mi, runtime'a mı?
|
||||||
|
|
||||||
|
### Karar
|
||||||
|
|
||||||
|
✅ **Net ayrım, frontend'i runtime kaygılarıyla yükleme:**
|
||||||
|
|
||||||
|
- **Frontend:** **yapı ve anlam** — tip, scope, dataflow. (Bu yol haritasının
|
||||||
|
konusu.)
|
||||||
|
- **Runtime/backend:** çekirdek/cihaz/tetikleme/çıktı formatı.
|
||||||
|
|
||||||
|
**Neden:** bu ayrım, kullanıcının önem verdiği **modülerliği korur**; frontend
|
||||||
|
backend-bağımsız kalır (ADR-006), böylece IR+VM ve ileride C-transpile aynı
|
||||||
|
frontend'den beslenir. Ayrıca **value-semantics + no-escape** kararının (kaçan
|
||||||
|
referans/closure yok) bağımlılığı buradadır: bu sayede scope-tabanlı bellek
|
||||||
|
çalışır (ADR-014). Closure veya interface değerleri eklemek bu ayrımı ve bellek
|
||||||
|
modelini birlikte zorlar — ikisi de bu yüzden ertelendi.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -379,11 +667,16 @@ bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır:
|
||||||
| ADR | Konu | Karar |
|
| ADR | Konu | Karar |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 006 | Frontend mimarisi | Çok-aşamalı; frontend/middle-end/backend katmanları |
|
| 006 | Frontend mimarisi | Çok-aşamalı; frontend/middle-end/backend katmanları |
|
||||||
| 007 | Analiz vs optimizasyon | Analiz yerinde işaretler; optimizasyon klonda dönüştürür |
|
| 007 | Analiz vs optimizasyon | Analiz yerinde işaretler; optimizasyon klonda dönüştürür; `clone()` merkezi, sembol tablosu remap edilir |
|
||||||
| 008 | Optimizasyon konumu | Basitler AST'de, dataflow gerektirenler IR'de |
|
| 008 | Optimizasyon konumu | Basitler AST'de, dataflow gerektirenler IR'de |
|
||||||
| 009 | Pass yönetimi | Fixpoint döngüsü, toggle'lı |
|
| 009 | Pass yönetimi | Fixpoint döngüsü, toggle'lı; monotonluk/iterasyon-tavanı değişmezi; akışa-bağlı analiz tur başına tazelenir |
|
||||||
| 010 | Tip sistemi | Minimal+genişletilebilir Type; gizli dönüşüm yok; Error tipi |
|
| 010 | Tip sistemi | Minimal+genişletilebilir Type; gizli dönüşüm yok; Error tipi; tamsayı literali bağlama-göre tiplenir |
|
||||||
| 011 | Scope/forward ref | Global'de forward ref, lokal'de declare-before-use (Java gibi) |
|
| 011 | Scope/forward ref | Global'de forward ref (fonksiyon/struct), ama global başlatıcı declare-before-use; lokal declare-before-use; döngüsel struct → `E010` |
|
||||||
| 012 | Node hiyerarşisi | ExpressionNode / StatementNode ara tabanları |
|
| 012 | Node hiyerarşisi | ExpressionNode / StatementNode ara tabanları |
|
||||||
| 013 | Analiz verisi yeri | Her şey AST'de; ref-count Symbol'da |
|
| 013 | Analiz verisi yeri | Her şey AST'de; ref-count Symbol'da |
|
||||||
| 014 | Dil kapsamı | Pointer/class/generic yok; struct+array+tipli fonksiyon var |
|
| 014 | Dil kapsamı | Pointer/class/generic/closure yok; struct+array+tipli fonksiyon var; scope-tabanlı bellek gerekçeli |
|
||||||
|
| 015 | Çalıştırma modeli | IR + bytecode VM; makine-kodu JIT kapsam dışı |
|
||||||
|
| 016 | FFI seam | Kasıtlı "host fonksiyonu çağır" mekanizması; `print` ilk müşteri |
|
||||||
|
| 017 | Batteries/stdlib | Sınır problemi; küçük builtin + FFI/kütüphane; ertelendi |
|
||||||
|
| 018 | `interface` | Ertelendi (reddedilmedi); struct+fonksiyon yeter |
|
||||||
|
| 019 | Frontend↔runtime | Frontend yapı+anlam; çekirdek/cihaz/çıktı runtime'a ait |
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,23 @@
|
||||||
> gelecek yol haritası hakkında kapsamlı analizleri içerir.
|
> gelecek yol haritası hakkında kapsamlı analizleri içerir.
|
||||||
> Her kararın **neden** alındığı, alternatiflerin neden elendiği ve
|
> Her kararın **neden** alındığı, alternatiflerin neden elendiği ve
|
||||||
> gelecekte hangi koşullarda tekrar değerlendirileceği belirtilmiştir.
|
> gelecekte hangi koşullarda tekrar değerlendirileceği belirtilmiştir.
|
||||||
|
>
|
||||||
|
> ⚠️ **Hizalama notu (sonraki oturum):** Aşağıdaki ADR-001 ve ADR-005, backend
|
||||||
|
> kod-üretimi seçeneklerini (LLVM/QBE/custom/C-transpile) ve "JIT" terimini
|
||||||
|
> tartışır. Sonradan **çalıştırma modeli netleşti** ve bazı ifadeler güncellendi:
|
||||||
|
>
|
||||||
|
> - **Birincil çalıştırma modeli = IR + bytecode VM** (yorumlayıcı döngü).
|
||||||
|
> Bkz. `docs/adr-frontend-analiz.md` **ADR-015**.
|
||||||
|
> - **Gerçek makine-kodu JIT kapsam DIŞIDIR** (tek faydası ham hız; öncelik
|
||||||
|
> determinizm + incelenebilirlik). Buradaki "JIT" geçişleri bu ışıkta okunmalı.
|
||||||
|
> - **C-transpile**, ileride geçerli bir **ikinci backend**'tir; QBE/custom/LLVM
|
||||||
|
> ise "makine kodu gerçekten gerekirse libgccjit/LLVM'e bağlan" çerçevesinde
|
||||||
|
> **çok uzak gelecektir**. ADR-001'deki karşılaştırmalar o gün için geçerli.
|
||||||
|
> - "HeavyIR/LightIR" ikiliği (ADR-005) bir **gelecek fikri** olarak durur; v0'ın
|
||||||
|
> IR+VM hedefi tek, basit bir IR'dir + **FFI seam** (ADR-016).
|
||||||
|
> - **Yapılan vs planlanan:** ADR-001'deki "mevcut durum" listesi hâlâ doğrudur
|
||||||
|
> (lexer/tokenizer/parser/AST + minimal IR deneyi çalışır); kod üretimi ve VM
|
||||||
|
> **henüz yoktur.**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,30 @@
|
||||||
# saQut Frontend Yol Haritası — Symbol Table + Semantic Analiz + Optimizasyon
|
# saQut Frontend Yol Haritası — Symbol Table + Semantic Analiz + Optimizasyon
|
||||||
|
|
||||||
> Bu belge, frontend'i tamamlamaya yönelik dosya-dosya uygulama planıdır.
|
> Bu belge, frontend'i tamamlamaya yönelik dosya-dosya uygulama planıdır.
|
||||||
> Kararların gerekçeleri: `docs/adr-frontend-analiz.md` (ADR-006…014).
|
> Kararların gerekçeleri: `docs/adr-frontend-analiz.md` (ADR-006…019).
|
||||||
> Tartışma akışı: `docs/transkript-frontend-tasarim.md`.
|
> Tartışma akışı: `docs/transkript-frontend-tasarim.md`.
|
||||||
>
|
>
|
||||||
> **İlke:** Sıralama katıdır — her faz bir öncekine dayanır. Her faz sonunda
|
> **İlke:** Sıralama katıdır — her faz bir öncekine dayanır. Her faz sonunda
|
||||||
> mevcut örneklerle (`examples/Final.sqt`, `examples/source.sqt`) ve CLI
|
> geçerli örnekle (`examples/fibonacci.sqt`, `examples/source.sqt`) ve CLI
|
||||||
> komutlarıyla doğrulama yapılır; regresyon olmamalıdır. Kod temiz, anlaşılır ve
|
> komutlarıyla doğrulama yapılır; regresyon olmamalıdır. Kod temiz, anlaşılır ve
|
||||||
> yorum satırlarıyla takip edilebilir olmalıdır (header-only tarzı korunur,
|
> yorum satırlarıyla takip edilebilir olmalıdır (header-only tarzı korunur,
|
||||||
> bkz. ADR-003).
|
> bkz. ADR-003).
|
||||||
|
>
|
||||||
|
> ⚠️ **Yapılan vs planlanan:** Bugün çalışan = lexer, tokenizer, Pratt parser,
|
||||||
|
> AST, AST'nin JSON serileştirmesi, CLI iskeleti, konum takibi, basit aritmetiği
|
||||||
|
> düşüren minimal IR deneyi. Bu yol haritasındaki **her şey planlıdır** (sembol
|
||||||
|
> tablosu, semantik analiz, tip sistemi, diagnostic, optimizasyon).
|
||||||
|
>
|
||||||
|
> 🎯 **Bu haftanın işi:** **sembol tablosu + iki-geçişli toplayıcı** (Faz 2),
|
||||||
|
> hedef **"fibonacci'yi derle ve çalıştır"** (`examples/fibonacci.sqt`). Faz 0–1
|
||||||
|
> bunun önkoşuludur.
|
||||||
|
>
|
||||||
|
> 🧭 **Önce dikey dilim, sonra çerçeve.** Bir şey çalışmadan önce genel pass
|
||||||
|
> manager / evrensel config / ağır soyutlama inşa etme. Uçtan uca tek bir dilim
|
||||||
|
> (kaynak → IR → çalıştır; tamsayı + değişken + kontrol akışı + tek `print`)
|
||||||
|
> önce çalışsın. Faz 4'ün framework'ü (OptimizationManager, fixpoint, config)
|
||||||
|
> ancak Faz 0–3 fibonacci'yi geçirdikten **sonra** anlam kazanır — erken
|
||||||
|
> soyutlama daha az değil, daha çok karmaşıklıktır.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -25,7 +41,8 @@ Faz 4 Optimizasyon Pass manager (fixpoint) + constant folding + dead code
|
||||||
Katman eşlemesi (ADR-006):
|
Katman eşlemesi (ADR-006):
|
||||||
- **Frontend:** Faz 0–3
|
- **Frontend:** Faz 0–3
|
||||||
- **Middle-end:** Faz 4
|
- **Middle-end:** Faz 4
|
||||||
- **Backend:** bu yol haritasının dışında (C transpile → QBE → JIT, ADR-001)
|
- **Backend:** bu yol haritasının dışında (birincil: IR + bytecode VM, ADR-015;
|
||||||
|
ileride: C transpile; makine kodu uzak gelecek — "JIT" kapsam dışı)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -46,21 +63,28 @@ Katman eşlemesi (ADR-006):
|
||||||
|
|
||||||
| Kod | Anlam | Hangi fazda üretilir |
|
| Kod | Anlam | Hangi fazda üretilir |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `E001` | Tanımsız değişken/isim | Faz 2/3 |
|
| `E001` | Tanımsız değişken/isim (declare-before-use ihlali dahil — lokal ve **global başlatıcı**, ADR-011) | Faz 2/3 |
|
||||||
| `E002` | Aynı scope'ta çift tanım | Faz 2 |
|
| `E002` | Aynı scope'ta çift tanım | Faz 2 |
|
||||||
| `E003` | Tip uyuşmazlığı | Faz 3 |
|
| `E003` | Tip uyuşmazlığı (gizli dönüşüm yok; literal için bağlama-göre kural, ADR-010) | Faz 3 |
|
||||||
| `E004` | Döngü/switch dışı `break`/`continue` | Faz 3 |
|
| `E004` | Döngü/switch dışı `break`/`continue` | Faz 3 |
|
||||||
| `E005` | Fonksiyon dışı `return` | Faz 3 |
|
| `E005` | Fonksiyon dışı `return` | Faz 3 |
|
||||||
| `E006` | Return tipi imzaya uymuyor | Faz 3 |
|
| `E006` | Return tipi imzaya uymuyor | Faz 3 |
|
||||||
| `E007` | Tanımsız tip (bilinmeyen tip adı) | Faz 2/3 |
|
| `E007` | Tanımsız tip (bilinmeyen tip adı) | Faz 2/3 |
|
||||||
| `E008` | Fonksiyon çağrısı argüman sayısı/tipi uyuşmuyor | Faz 3 |
|
| `E008` | Fonksiyon çağrısı argüman sayısı/tipi uyuşmuyor | Faz 3 |
|
||||||
| `E009` | Array boyutu sabit değil / geçersiz | Faz 3 |
|
| `E009` | Array boyutu sabit değil / geçersiz | Faz 3 |
|
||||||
|
| `E010` | **Özyinelemeli/döngüsel struct tanımı** (by-value çevrim → sonsuz boyut, ADR-011) | Faz 2/3 |
|
||||||
| `W001` | Kullanılmayan değişken | Faz 4 |
|
| `W001` | Kullanılmayan değişken | Faz 4 |
|
||||||
| `W002` | Sıfıra bölme (sabit folding) | Faz 4 |
|
| `W002` | Sıfıra bölme (sabit folding) | Faz 4 |
|
||||||
| `W003` | Erişilemez (ölü) kod | Faz 4 |
|
| `W003` | Erişilemez (ölü) kod | Faz 4 |
|
||||||
|
|
||||||
*(Liste uygulamada genişleyebilir; yeni hatalar buraya eklenir.)*
|
*(Liste uygulamada genişleyebilir; yeni hatalar buraya eklenir.)*
|
||||||
|
|
||||||
|
**Literal / başlatıcı kuralları (ADR-010/011) hata kataloğunu nasıl etkiler:**
|
||||||
|
- `float x = 1;` → **hata değil** (tamsayı literali bağlama-göre tiplenir,
|
||||||
|
kayıpsız). `int y = 1.5;` → `E003` (kayıp). `float x = anInt;` → `E003`
|
||||||
|
(değişken→değişken gizli dönüşüm yok).
|
||||||
|
- `int a = b; int b = 5;` (global) → `E001` (global başlatıcı declare-before-use).
|
||||||
|
|
||||||
### Doğrulama
|
### Doğrulama
|
||||||
- `Type::equals` / `toString` birim testleri.
|
- `Type::equals` / `toString` birim testleri.
|
||||||
- `DiagnosticEngine` topla → `printAll` çıktısı doğru sıralı.
|
- `DiagnosticEngine` topla → `printAll` çıktısı doğru sıralı.
|
||||||
|
|
@ -83,7 +107,11 @@ ayır, analiz alanlarını ekle. İlgili ADR: 012, 013.
|
||||||
| `src/parser/nodes/*.cpp` | `toJson()`/`log()`'a yeni alanları (tip, isReachable) ekle — boş cpp'ler doluyor. |
|
| `src/parser/nodes/*.cpp` | `toJson()`/`log()`'a yeni alanları (tip, isReachable) ekle — boş cpp'ler doluyor. |
|
||||||
|
|
||||||
### Doğrulama
|
### Doğrulama
|
||||||
- `saqut ast examples/Final.sqt` hâlâ geçerli JSON (regresyon yok, `python3 -m json.tool` ile).
|
- `saqut ast examples/fibonacci.sqt` hâlâ geçerli JSON (regresyon yok,
|
||||||
|
`python3 -m json.tool` ile). Parser regresyonu için ayrıca
|
||||||
|
`examples/parser-stress/Final.sqt` de geçerli JSON üretmeye devam etmeli (bu
|
||||||
|
dosya **geçerli program değildir**, yalnızca parser/AST stres fixture'ıdır —
|
||||||
|
semantik fazlarda fixture olarak kullanılmaz).
|
||||||
- Derleme uyarısız (`-Wall -Wextra`).
|
- Derleme uyarısız (`-Wall -Wextra`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -105,12 +133,20 @@ ayır, analiz alanlarını ekle. İlgili ADR: 012, 013.
|
||||||
### Notlar
|
### Notlar
|
||||||
- Scope oluşturan node'lar: Program, FunctionDecl (parametreler), Block, for/while.
|
- Scope oluşturan node'lar: Program, FunctionDecl (parametreler), Block, for/while.
|
||||||
- `src/json.hpp`'deki eski `collectSymbolsRecursive` bu sistemle değiştirilir.
|
- `src/json.hpp`'deki eski `collectSymbolsRecursive` bu sistemle değiştirilir.
|
||||||
- Tanımsız isim → `E001`; bilinmeyen tip → `E007`.
|
- Tanımsız isim → `E001`; bilinmeyen tip → `E007`; çift tanım → `E002`.
|
||||||
|
- **Döngüsel struct kontrolü (`E010`):** Geçiş 1'den sonra struct'lar düğüm,
|
||||||
|
"alanı olarak içerir" kenarıyla bir çevrim-arama (DFS) çalıştır; çevrim →
|
||||||
|
`E010` (ADR-011). Pointer olmadığı için tüm kapsama by-value'dur; çevrim =
|
||||||
|
sonsuz boyut.
|
||||||
|
- **Global başlatıcı declare-before-use (ADR-011):** fonksiyon/struct tam hoist
|
||||||
|
edilir, global değişken **ismi** hoist edilir, ama global değişken
|
||||||
|
**başlatıcısı** kendinden önce tanımlı isimleri kullanabilir; aksi → `E001`.
|
||||||
|
|
||||||
### Doğrulama
|
### Doğrulama
|
||||||
- `saqut symbols examples/Final.sqt` → zengin tablo (her sembolün tipi, tanım yeri,
|
- `saqut symbols examples/fibonacci.sqt` → zengin tablo (her sembolün tipi, tanım
|
||||||
referansları). Forward reference çalışır (sonra tanımlı fonksiyon çağrılabilir).
|
yeri, referansları). Forward reference çalışır (sonra tanımlı fonksiyon
|
||||||
- Hatalı örnekler → `E001`/`E002`/`E007` diagnostic'leri.
|
çağrılabilir — `main`, `fibonacci`'yi çağırır).
|
||||||
|
- Hatalı örnekler → `E001`/`E002`/`E007`/`E010` diagnostic'leri.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -123,7 +159,7 @@ doğrula. İlgili ADR: 010, 013.
|
||||||
|
|
||||||
| Dosya | İçerik |
|
| Dosya | İçerik |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `src/sema/type_checker.hpp/.cpp` | İfadeleri alttan üste gez, her `ExpressionNode`'a `resolvedType` ata. Gizli dönüşüm yok (ADR-010) → uyuşmazlıkta `E003`. Kontrol noktaları: atama (`=`), binary op operand tipleri, fonksiyon çağrısı argümanları (`E008`), array index, return değeri (`E006`), variable init tip uyumu. Hata olunca node'a `Type::error()` → ardışık sahte hata yok. |
|
| `src/sema/type_checker.hpp/.cpp` | İfadeleri alttan üste gez, her `ExpressionNode`'a `resolvedType` ata. Gizli **değişken→değişken** dönüşüm yok (ADR-010) → uyuşmazlıkta `E003`. **Tamsayı literali bağlama-göre tiplenir** (kayıpsızsa beklenen tipe uyar; `float x = 1;` geçerli, `int y = 1.5;` → `E003`). Kontrol noktaları: atama (`=`), binary op operand tipleri, fonksiyon çağrısı argümanları (`E008`), array index, return değeri (`E006`), variable init tip uyumu. Hata olunca node'a `Type::error()` → ardışık sahte hata yok. |
|
||||||
| `src/sema/structural_validator.hpp/.cpp` | Parent pointer ile ağaç-tırmanma kontrolleri: `break`/`continue` döngü/switch içinde mi (`E004`), `return` fonksiyon içinde mi (`E005`), array boyutu sabit mi (`E009`). |
|
| `src/sema/structural_validator.hpp/.cpp` | Parent pointer ile ağaç-tırmanma kontrolleri: `break`/`continue` döngü/switch içinde mi (`E004`), `return` fonksiyon içinde mi (`E005`), array boyutu sabit mi (`E009`). |
|
||||||
|
|
||||||
### Notlar
|
### Notlar
|
||||||
|
|
@ -148,7 +184,7 @@ optimizasyon. **Orijinali bozmaz — klon üstünde** (ADR-007). İlgili ADR: 00
|
||||||
|---|---|
|
|---|---|
|
||||||
| `src/core/config.hpp` | `CompilerConfig`: pass toggle'ları (`optConstantFolding`, `optDeadCodeElim`, …), `outputFormat`, `mode`, `optimized` bayrağı. |
|
| `src/core/config.hpp` | `CompilerConfig`: pass toggle'ları (`optConstantFolding`, `optDeadCodeElim`, …), `outputFormat`, `mode`, `optimized` bayrağı. |
|
||||||
| `src/opt/optimization_pass.hpp` | Soyut `OptimizationPass`: `virtual bool run(ASTNode* root, SymbolTable* table) = 0;` (değişiklik yaptıysa true). `name()`. |
|
| `src/opt/optimization_pass.hpp` | Soyut `OptimizationPass`: `virtual bool run(ASTNode* root, SymbolTable* table) = 0;` (değişiklik yaptıysa true). `name()`. |
|
||||||
| `src/opt/optimization_manager.hpp` | Pass listesi; `CompilerConfig`'e göre seçim; **fixpoint döngüsü** (hiçbir pass değişiklik yapmayana kadar). Çalışmadan önce AST'yi **klonlar** (`ASTNode::clone()` gerekebilir). |
|
| `src/opt/optimization_manager.hpp` | Pass listesi; `CompilerConfig`'e göre seçim; **fixpoint döngüsü** (hiçbir pass değişiklik yapmayana kadar + **sert iterasyon tavanı** `maxFixpointRounds`, ADR-009). **Sonlanma değişmezi:** havuzdaki pass'ler monoton (yalnızca küçültür); büyüten pass (inlining) eklenirse tavan zorunlu. Çalışmadan önce AST'yi **klonlar** — `ASTNode::clone()` **merkezi bir bileşendir** (ADR-007): parent pointer'lar yeniden bağlanır, sembol tablosu klonlanıp `IdentifierNode→Symbol` bağları **remap** edilir. **Her turda**, klon üzerinde akışa-bağlı analiz (`isReachable`, ref-count) **yeniden hesaplanır** (ADR-009); aksi halde zincirleme fırsatlar bayat veriyle kaçar. |
|
||||||
| `src/opt/constant_folding.hpp/.cpp` | `BinaryExpression` operandları sabitse hesapla, sonucu sabit `Literal` ile değiştir (klonda). Tipe saygılı (`5/2`→int `2`, ADR-010). Sıfıra bölme → `W002`, katlama yapma. |
|
| `src/opt/constant_folding.hpp/.cpp` | `BinaryExpression` operandları sabitse hesapla, sonucu sabit `Literal` ile değiştir (klonda). Tipe saygılı (`5/2`→int `2`, ADR-010). Sıfıra bölme → `W002`, katlama yapma. |
|
||||||
| `src/opt/dead_code_elim.hpp/.cpp` | `isReachable` (Faz 3) işaretine göre: `return`/`break`/`continue` sonrası statement'lar, `if(false)`, sıfır-referanslı değişken (`W001`/`W003`). |
|
| `src/opt/dead_code_elim.hpp/.cpp` | `isReachable` (Faz 3) işaretine göre: `return`/`break`/`continue` sonrası statement'lar, `if(false)`, sıfır-referanslı değişken (`W001`/`W003`). |
|
||||||
|
|
||||||
|
|
@ -174,6 +210,17 @@ Bu yol haritası bittiğinde frontend tamamlanmış olur:
|
||||||
- Opsiyonel, incelenebilir optimizasyon.
|
- Opsiyonel, incelenebilir optimizasyon.
|
||||||
|
|
||||||
Sonraki adım (ayrı yol haritası): **IR güçlendirme** (kontrol akışı/fonksiyon/
|
Sonraki adım (ayrı yol haritası): **IR güçlendirme** (kontrol akışı/fonksiyon/
|
||||||
bellek opcode'ları, ADR-005/Issue 5.1) → **C transpile backend** → QBE → JIT
|
bellek opcode'ları + **FFI seam** `callhost`, ADR-016) → **bytecode VM ile
|
||||||
(ADR-001 sırası). Dinamik array'in runtime bellek modeli (ADR-014) backend
|
çalıştırma** (ADR-015) → hedef: **`examples/fibonacci.sqt` derlenir ve çalışır.**
|
||||||
fazında kararlaştırılır.
|
|
||||||
|
- **Çalıştırma modeli IR + bytecode VM'dir** (ADR-015). **Makine-kodu JIT
|
||||||
|
açıkça kapsam dışıdır;** öncelik determinizm + incelenebilirlik, ham hız değil.
|
||||||
|
- **C transpile**, ileride geçerli bir **ikinci** backend olarak kalır (frontend
|
||||||
|
backend-bağımsız). Makine kodu gerçekten istenirse libgccjit/LLVM'e bağlanılır
|
||||||
|
— çok uzak gelecek.
|
||||||
|
- IR/VM tasarlanırken **FFI seam'i şimdiden bırak** (ADR-016); `print` ilk
|
||||||
|
müşteridir. Bellek host (C++) heap'idir; özel allocator yok. Dinamik array'in
|
||||||
|
runtime modeli (ADR-014) bu fazda netleşir.
|
||||||
|
|
||||||
|
> Çerçeve uyarısı: bu sonraki adım da **önce dikey dilim** ilkesine tabidir —
|
||||||
|
> genel VM/optimizasyon altyapısı kurmadan önce fibonacci uçtan uca çalışsın.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// saQut — geçerli örnek program (semantik analiz + kod üretimi fixture'ı)
|
||||||
|
//
|
||||||
|
// Kilitlenmiş tasarıma uyar: prosedürel, value semantics, kullanıcıya açık
|
||||||
|
// pointer yok, tek main, struct/array gerektirmez. Birinci kilometre taşının
|
||||||
|
// ("fibonacci'yi derle ve çalıştır") referans programıdır.
|
||||||
|
//
|
||||||
|
// İlk ifade doğrudan bir fonksiyon tanımı olabilir; zorunlu class/main
|
||||||
|
// boilerplate'i yoktur (Java'nın aksine).
|
||||||
|
|
||||||
|
int fibonacci(int n) {
|
||||||
|
if (n <= 1) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return fibonacci(n - 1) + fibonacci(n - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fibonacciIterative(int n) {
|
||||||
|
int first = 0;
|
||||||
|
int second = 1;
|
||||||
|
for (int i = 0; i < n; i = i + 1) {
|
||||||
|
int next = first + second;
|
||||||
|
first = second;
|
||||||
|
second = next;
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int n = 10;
|
||||||
|
print(fibonacci(n)); // recursive
|
||||||
|
print(fibonacciIterative(n)); // iterative
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Parser Stres Fixture'ları
|
||||||
|
|
||||||
|
Buradaki dosyalar **yalnızca parser/AST'yi zorlamak** için yazılmıştır.
|
||||||
|
**Geçerli saQut programı değildirler** ve semantik analiz / kod üretimi için
|
||||||
|
fixture olarak **kullanılmamalıdır**.
|
||||||
|
|
||||||
|
## `Final.sqt`
|
||||||
|
|
||||||
|
Tarihsel olarak parser'ın token/AST kapsamını test etmek için kullanıldı
|
||||||
|
(289 token, 200+ AST node). Ancak kilitlenmiş dil tasarımını birden çok yerde
|
||||||
|
**ihlal eder**:
|
||||||
|
|
||||||
|
- **Kullanıcıya açık pointer kullanımı** (`struct List*`, `->`) — dilde `*`/`&`
|
||||||
|
yoktur (bkz. ADR-014).
|
||||||
|
- **Sabit boyutlu array** (`int arr[100]`) — array tipi `int[]`'tir, boyut tipin
|
||||||
|
parçası değildir (bkz. ADR-010).
|
||||||
|
- **İki `int main()` tanımı** — aynı scope'ta çift tanım yasaktır (ADR-011, `E002`).
|
||||||
|
- `printf` format-string semantiği — dilin builtin'i `print`'tir; format'lı
|
||||||
|
çıktı bir kütüphane/FFI işidir (bkz. ADR-017).
|
||||||
|
|
||||||
|
Geçerli, küçük bir örnek için `examples/fibonacci.sqt`'ye bakın.
|
||||||
268
readme.md
268
readme.md
|
|
@ -1,127 +1,185 @@
|
||||||
# Syntax
|
# saQut
|
||||||
|
|
||||||
Syntax modunda 2 seçenek bulunmaktadır
|
**Programlanabilir, incelenebilir bir derleyici — bir "alet çantası" (toolbox).**
|
||||||
- JIR: Söz dizimi tamamen Java programlama diline uygun olarak parse edilmektedir. Compiling, transpiling desteklenir Interpreter desteklenmez
|
|
||||||
- CIR: Söz dizimi tamamen C programlama diline uygun olarak parse edilir. Compiling ve Interpreter desteklenir. transpiling desteklenmez
|
|
||||||
|
|
||||||
# Compiler short options
|
saQut'un asıl varlık sebebi dilin kendisinden çok, **derleme sürecinin her
|
||||||
|
aşamasının dışarıdan görülebilir ve müdahale edilebilir olmasıdır.** Token'lar,
|
||||||
|
AST, sembol tablosu, optimizasyonun öncesi/sonrası ve IR — hepsi ayrı ayrı
|
||||||
|
incelenebilir. Dil, bu aletin üzerinde çalıştığı küçük, prosedürel bir
|
||||||
|
örnektir; vitrin değil, alet.
|
||||||
|
|
||||||
|
Uygulama dili **C++**'tır (header-only eğilimli, bkz. `docs/fikirler.md` ADR-003).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Şu an ne çalışıyor, ne çalışmıyor
|
||||||
|
|
||||||
|
Belgeler **planlanan** ile **yapılan**ı net ayırır. Bugünkü gerçek durum:
|
||||||
|
|
||||||
|
### ✅ Çalışıyor (built)
|
||||||
|
- **Lexer** — karakter seviyesi tarama, konum takibi.
|
||||||
|
- **Tokenizer** — token üretimi (6 token tipi), yorum satırı desteği.
|
||||||
|
- **Pratt parser** — ifade (Pratt) + statement (recursive descent) ayrıştırma.
|
||||||
|
- **AST** — fonksiyon, blok, değişken tanımı, if/for/while/do-while/return,
|
||||||
|
ifade node'ları.
|
||||||
|
- **AST'nin JSON serileştirmesi** — `saqut ast` ile incelenebilir.
|
||||||
|
- **CLI komut yapısı** — `tokens`, `ast`, `symbols`, `run` iskeletleri.
|
||||||
|
- **Kaynak konum takibi** (SourceLocation) — offset → (satır, sütun).
|
||||||
|
- **Minimal IR deneyi** — basit aritmetiği düşürür (örn. `1 + (7/3)` → kısa
|
||||||
|
doğrusal komut dizisi). Henüz tam bir backend değil, bir deneydir.
|
||||||
|
|
||||||
|
### 🚧 Henüz yok (planned)
|
||||||
|
- Sembol tablosu
|
||||||
|
- Semantik analiz
|
||||||
|
- Tip sistemi
|
||||||
|
- Diagnostic (hata raporlama) motoru
|
||||||
|
- Optimizasyon
|
||||||
|
- IR + bytecode VM ile çalıştırma
|
||||||
|
|
||||||
|
> `feature/frontend-analysis` dalı şu an yalnızca bu yapılmamış işin **tasarım
|
||||||
|
> belgelerini** içerir, kodunu değil.
|
||||||
|
|
||||||
|
**Birinci kilometre taşı ("bitti" tanımı):** derleyici **fibonacci'yi**
|
||||||
|
(recursive + iterative) ve basit matematik/döngü programlarını **derleyip
|
||||||
|
çalıştırabilmeli.** Referans program: `examples/fibonacci.sqt`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dil kimliği (kilitli)
|
||||||
|
|
||||||
|
Prosedürel, **C ailesi sözdizimi**, **value semantics**. İlk ifade doğrudan bir
|
||||||
|
işlem/tanım olabilir; zorunlu class/`main` boilerplate'i yoktur (Java'nın aksine).
|
||||||
|
|
||||||
|
| Özellik | Karar |
|
||||||
|
|---|---|
|
||||||
|
| Class / OOP / kalıtım | **Yok** |
|
||||||
|
| Closure | **Yok** |
|
||||||
|
| Generic | **Yok** |
|
||||||
|
| Kullanıcıya açık pointer (`*` / `&`) | **Yok** — derleyici/runtime içeride pointer'ı serbestçe kullanır |
|
||||||
|
| `struct` | **Var** |
|
||||||
|
| Tipli fonksiyonlar (dönüş + parametre) | **Var** |
|
||||||
|
| Array (`int[]`) | **Var** |
|
||||||
|
| `interface` | **Ertelendi** (v0 değil — gerekçe ADR-018) |
|
||||||
|
| `auto` / tip çıkarımı | **Yok** |
|
||||||
|
| Gizli int↔float dönüşümü | **Yok** (tek istisna: sabit folding) |
|
||||||
|
|
||||||
|
Gerekçe: prosedürel tasarım semantik karmaşıklığı en aza indirir ve hedeflerle
|
||||||
|
(fibonacci, matematik, sıralama, ayrıştırma) örtüşür. Standart C'de `class`
|
||||||
|
yoktur (o C++'tır); C, struct + fonksiyonun yettiğini kanıtlar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Çalıştırma modeli (kilitli): IR + bytecode VM
|
||||||
|
|
||||||
|
saQut, kendi **IR**'sine derler ve bu IR'yi bir **yorumlayıcı döngü (bytecode
|
||||||
|
VM)** ile çalıştırır.
|
||||||
|
|
||||||
|
- **Tree-walker DEĞİL** (çok yavaş).
|
||||||
|
- **Gerçek makine-kodu JIT DEĞİL.** Makine kodu üretimi (register allocation,
|
||||||
|
ABI/çağırma sözleşmeleri, çalıştırılabilir `mmap` bellek) **kapsam dışıdır** —
|
||||||
|
tek faydası ham hızdır ve hız burada öncelik değildir. Öncelikler
|
||||||
|
**determinizm** ve **incelenebilirliktir**; bytecode VM ikisini de doğrudan
|
||||||
|
sağlar.
|
||||||
|
- **Bellek bu modelde kolaydır:** host (C++) heap'i kullanılır; v0 için özel
|
||||||
|
runtime allocator gerekmez.
|
||||||
|
- **C'ye transpile, geçerli bir İKİNCİ backend olarak ileride kalır** (frontend
|
||||||
|
backend-bağımsızdır — middle-end ayrımının amacı budur, ADR-006). İleride
|
||||||
|
makine kodu istenirse elle code generator yazmak yerine **libgccjit / LLVM'e
|
||||||
|
bağlanılır** — ama bu çok uzak gelecektir.
|
||||||
|
|
||||||
|
> Eski belge/konuşmalarda geçen "JIT" terimi yanlış yönlendiricidir; doğru
|
||||||
|
> çerçeve **IR + VM**'dir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mimari hatlar
|
||||||
|
|
||||||
```
|
```
|
||||||
sqt kaynak kodunu çallıştırır
|
KAYNAK KOD
|
||||||
saqut file:sourcecode.sqt
|
│ lexer
|
||||||
|
▼
|
||||||
sqt kaynak kodunu C koduna sonrada makine koduna derler. GCC gereklidir
|
TOKEN'LAR ────────────── saqut tokens
|
||||||
saqut compile file:sourcecode.sqt output:program.exe
|
│ parser (Pratt + recursive descent)
|
||||||
|
▼
|
||||||
Derleyicinin olduğu gibi çalıştırılması interpreter moduna alır, konsola yazılan kodları alır çalıştırır outputu loglar
|
AST ──────────────────── saqut ast
|
||||||
saqut
|
│ sembol toplama (iki geçişli) ┐
|
||||||
|
▼ │
|
||||||
Derleyici kodu alır ve IR üretir
|
SEMBOL TABLOSU ───────── saqut symbols │ FRONTEND
|
||||||
saqut parse file:sourcecode.sqt output:program.ces
|
│ semantik analiz (annotation) │ (yapı + anlam)
|
||||||
|
▼ │
|
||||||
Derleyici IRyi alır ve çalıştırır. Burda kaynak kodu veya IR olup olmadığını otomatik anlar
|
ANNOTATE EDİLMİŞ AST ─── saqut ast ┘
|
||||||
saqut file:sourcecode.ces
|
│ optimizasyon (opsiyonel, klon üstünde) ── MIDDLE-END
|
||||||
|
▼
|
||||||
Derleyici IRyi veya kaynak kodunu alır C diline çevirir
|
IR ───────────────────── (planlanan) ┐
|
||||||
saqut transpile file:sourcecode.ces output:program.c
|
│ bytecode VM / yorumlayıcı döngü │ BACKEND
|
||||||
|
▼ │ (çalıştırma + FFI seam)
|
||||||
Derleyici kaynak kodu ASTsini çıkarır ve kaydeder
|
ÇALIŞTIRMA / ÇIKTI ───── saqut run ┘
|
||||||
saqut file:sourcecode.sqt ast:sourcecode.xml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **Frontend** yapıyı ve anlamı modeller (tip, scope, dataflow).
|
||||||
|
- **"Hangi çekirdek, hangi cihaz, ne zaman, hangi çıktı formatı"** runtime/backend
|
||||||
|
meselesidir — frontend'e yüklenmez.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Compiler Structure
|
## CLI (mevcut + planlanan)
|
||||||
|
|
||||||
## 1 Source Code
|
```
|
||||||
|
# --- çalışıyor ---
|
||||||
|
saqut tokens file:kaynak.sqt # token listesi
|
||||||
|
saqut ast file:kaynak.sqt # AST (JSON)
|
||||||
|
saqut symbols file:kaynak.sqt # sembol tablosu (iskelet)
|
||||||
|
|
||||||
- Yazılan kaynak kodun derleyiciye aktarılması
|
# --- planlanan ---
|
||||||
- Derleyici için belirlenen seçenekler ile derleyici yapısının yeniden yapılandırılması
|
saqut run file:kaynak.sqt # IR üret + bytecode VM ile çalıştır
|
||||||
- Derleyicinin outputlarının ayarlanması ve çıkışlarının aktarılması
|
saqut ast file:kaynak.sqt --optimized # klon, optimize edilmiş AST (öncesi/sonrası)
|
||||||
|
saqut transpile file:kaynak.sqt -o prog.c # ikinci backend (ileride)
|
||||||
|
```
|
||||||
|
|
||||||
## 2 Lexing
|
Tasarım gereği her aşamanın çıktısı erken bir noktada dosyalanabilir/loglanabilir
|
||||||
|
(programlanabilir derleyici). Token, ham AST, optimize AST ve IR ayrı ayrı
|
||||||
|
kaydedilebilir.
|
||||||
|
|
||||||
Kaynak kodun içindeki tüm harflerin gezilip tek parça büyük bir token listesinin oluşturulması
|
---
|
||||||
|
|
||||||
Bu işlemin sonucunda kaynak kodun içindeki tüm yapılar; semboller, sayılar, stringler ve operatörler olarak 4 kategoriye ayrılır
|
## Batteries / stdlib — kuzey yıldızı, ertelendi
|
||||||
|
|
||||||
## 3 Tokenning
|
Gerçek bir genel sürüm pil ile gelmeli (sıralama, sıkıştırma, kripto,
|
||||||
|
JSON/XML/HTML ayrıştırma). Ama bu **bugünün işi ve v0.1 değildir.**
|
||||||
|
|
||||||
Tüm tokenler gezilerek bir Abstract Syntax Tree ağacı (AST) oluşturulur. Tek düze tokenler bu aşamada hiyerarşik olarak
|
Mimari çerçeve (monolit korkusunu önler): derleyici pilleri çekirdeğine
|
||||||
|
gömmez. Bunun yerine **küçük bir gerçek builtin kümesi** (`print`, temel
|
||||||
|
zorunlular) + **gerisi kütüphane/FFI** ile gelir. "Batteries" sorunu aslında
|
||||||
|
bir **sınır (FFI/link seam) sorunudur**, "zlib'i yeniden yaz" sorunu değil.
|
||||||
|
Sınır bir kez çizilir, piller üstünde sonsuza dek birikir.
|
||||||
|
|
||||||
File -> Class -> Methods -> Expressions / Statements -> Volumes -> Values
|
- **JSON/XML/HTML ayrıştırıcıları saQut'un kendisinde yazılabilir** (string +
|
||||||
|
struct + fonksiyon + kontrol akışı yeter). İlk gerçek demo programları.
|
||||||
|
- **Sıkıştırma/kripto:** denenmiş C kütüphanelerine FFI ile bağlan. **Kripto
|
||||||
|
asla elle yazılmaz.**
|
||||||
|
- **Bugüne tek yansıması:** IR/runtime tasarlanırken **bilinçli bir FFI seam**
|
||||||
|
("host fonksiyonu çağır" deliği) bırakılır. `print` bunu zaten zorlar — bunu
|
||||||
|
kaza değil, **kasıtlı bir mekanizma** yapıyoruz (ADR-016).
|
||||||
|
|
||||||
Şeklinde bir ağaç yapısına kavuşur. Böylece yazılan kaynak kodu anlaşılır ilk yapısına kavuşur
|
---
|
||||||
|
|
||||||
## 4 Parsing
|
## Belge haritası
|
||||||
|
|
||||||
Oluşturulan AST ağacı anlamlaştırılır ve zenginleştirilir. Tanımlanan değerler, fonksiyonlar, classler ve değişkenler belirlenir. Tip kontrolleri ve Syntax hataları burada keşfedilir. Ayrıca Ulaşılamayan kod alanları, sınıfların ulaşılamayan (private) accessorları kontrol edilir, tüm bir kod boyunca class, tipleme, değişken ve döngülerin kullanım adetleri analiz edilir. Sistem içinde kullanılan tüm yapılar için geniş kapsamlı bir Symbol tablosu oluşturulur
|
| Belge | İçerik |
|
||||||
|
|---|---|
|
||||||
|
| `docs/fikirler.md` | ADR-001…005: backend stratejisi, parser, header-only, token, IR |
|
||||||
|
| `docs/adr-frontend-analiz.md` | ADR-006…019: frontend, analiz/optimizasyon, çalıştırma modeli, FFI, interface, bellek |
|
||||||
|
| `docs/roadmap-frontend.md` | Faz-faz uygulama planı (sembol tablosu → fibonacci) |
|
||||||
|
| `docs/transkript-frontend-tasarim.md` | Tasarım oturumunun transkripti |
|
||||||
|
| `examples/fibonacci.sqt` | Geçerli referans program (semantik + kod üretimi fixture'ı) |
|
||||||
|
| `examples/parser-stress/` | Yalnızca parser'ı zorlayan, **geçerli olmayan** fixture'lar |
|
||||||
|
|
||||||
## 5 Optimizing
|
---
|
||||||
|
|
||||||
Zenginleştirilmiş AST üzerindeki analizler üzerinden bazı AST dalları silinir, değiştirilir veya yeni dallar eklenebilir
|
## İlke
|
||||||
|
|
||||||
- Constant Folding : 4 + 1 gibi sonucu belli olan ifadeler 5 olarak tutulur
|
Bir şey çalışmadan önce çerçeve inşa etmekten kaçın. Önce **uçtan uca tek bir
|
||||||
- Dead Code Elimination : returnden sonraki kod bloğunun silinmesi veya if(false) ve dengi statementlerin yapıdan kaldırılması
|
dikey dilim** çalıştır (kaynak → IR → çalıştır; tamsayı aritmetiği + değişken +
|
||||||
- Matematiksel olarak değişmez kodların kaldırılması x * 1, x+0, x * 1 gibi valuelerin direkt x olarak değiştirilmesi
|
kontrol akışı + tek bir `print`). Modülerlik bir kuzey yıldızıdır, v0.1
|
||||||
- Hiç kullanılmayan değişkenlerin kaldırılması
|
gereksinimi değil; ihtiyaç doğmadan eklenen her soyutlama **daha az değil, daha
|
||||||
- Sabit (const) değerlerin döngülerin dışına çıkarılması veya programın globaline taşınması
|
çok** karmaşıklıktır.
|
||||||
- Null Check Elimination : Daha önce nullcheck yapılmış bir değişkenin tekrar nullcheck yapılan kontrollerini devredışı bırakmak
|
|
||||||
- Type Check Elimination : Daha önce typecheck yapılmış bir değişkenin tekrar typecheck yapılan kontrollerini devredışı bırakmak
|
|
||||||
|
|
||||||
## 6 Compiling
|
|
||||||
|
|
||||||
Oluşturulmuş tüm AST ağacını tamamen aynı işi yapan daha alt bir veri kümesine indirgeme işidir. Bellekteki AST yapısı ardışık komutlar dizisine çevrilir (Intermediate Representation) IR daha sonra tekrar okunup çalıştırılabilir.
|
|
||||||
|
|
||||||
Daha sonra IR ile kurulacak yapı ile bazen HeavyIR bazende LightIR üretilir.
|
|
||||||
LightIR, en temiz ve hızlı ancak hiç bir ayrıntı içermeyen koddur. Kaynak kodun çalıştırılması için mükemmel veridir ancak debug verilerinden yoksundur
|
|
||||||
HeavyIR, kaynak kodu verilerinin yanı sıra orjinal AST üzerinde tanımlanmış değişken isimleri ayrıntıları ve tiplemeleride içerir. LightIRye göre daha ayrıntılı ve büyüktür ancak debugging ve kaynak kodun parça parça okunduğu durumlar için (örneğin interpreter) kullanışlıdır
|
|
||||||
|
|
||||||
## 7 Interpreting
|
|
||||||
|
|
||||||
Derleyici HeavyIR üretir ve Symbol tablosunu silmez.
|
|
||||||
Optimizasyonların çoğu kapatılır.
|
|
||||||
Oluşturulmuş HeavyIR kodu çalıştırılır çalışma bittikten sonra stackframe kapatılmaz yeni girişler beklenir. Yeni kaynak kodu girişleri yapıldığında yine derlenir ve anında çalıştırılır. Yeni çalıştırılan kaynak kodu bir önceki stackframe içersinde symbol tablosu dikkate alınarak output üretir böylece önceki değerler halen kullanılabilir
|
|
||||||
|
|
||||||
## or 7 Executing
|
|
||||||
|
|
||||||
Derleyici LightIR üretir IR oluşturulduktan sonra symbol tablosu silinir.
|
|
||||||
Üretilen IR otomatize edilmiş bellekte yüksek performans ile çalıştırılır.
|
|
||||||
|
|
||||||
Derleyici o an ürettiği kaynak kodu anında çalıştırdığı (JIT) gibi
|
|
||||||
Daha önce üretilmiş ve depolanmış IR kodunuda çalıştırabilir
|
|
||||||
|
|
||||||
## or 7 Transpiling
|
|
||||||
|
|
||||||
Derleyici HeavyIR üretir ve Symbol tablosunu silmez.
|
|
||||||
Derleyici IR üretmez bunun yerine AST Üzerinden yeni bir dile çevrilir.
|
|
||||||
Duruma göre daha üst bir seviye dile dönüşüm yapıldığı gibi daha alt bir dile dönüşüm yapılabilir. IR üretilmez bunun yerine alınan kaynak kodu farklı bir kaynak koduna çevrilir
|
|
||||||
|
|
||||||
# programmable compiler
|
|
||||||
|
|
||||||
Derleyici tek seferde kaynak kodu alıp okuyup çalıştırabilir veya derleyebilir.
|
|
||||||
Ayrıca debug ortamlarında veya daha ayrıntılı projelerde derleme anına müdehale edilebilir
|
|
||||||
|
|
||||||
## Stage Session
|
|
||||||
|
|
||||||
Derleyiciye verilen bazı parametreler ile Lexer ve Tokenizer anında bazı işlemlerin yapılması engellenebilir
|
|
||||||
Örneğin accessorler kapatılabilir, hexedecimal sayılar kapatılabilir. Veya class olmadan globale yazılmış kodlar engellenebilir
|
|
||||||
|
|
||||||
## AST Session
|
|
||||||
|
|
||||||
Derleyiciye verilen bazı parametreler ile class yapılarına müdehale edilebilir, tipleme sistemleri sabitlenebilir, tek bir metot içerisine yazılacak kod sınırlanabilir veya for içerisinde for döngüsü kısıtlanabilir. Yazılan kod için analizler sonucunda bazı bloklar görmezden gelinebilir veya manipüle edilebilir
|
|
||||||
|
|
||||||
## Optimizing Session
|
|
||||||
|
|
||||||
Optimizasyon aşamaları parametreler ile tek tek açılabilir veya kapatılabilir
|
|
||||||
|
|
||||||
## Output Session
|
|
||||||
|
|
||||||
Derleyici ürettiği veriyi erken bir aşamada dosyalayabilir ve loglayabilir.
|
|
||||||
Derleyicinin oluşturduğui token, Pure AST, Optimized AST, LightIR veya HeavyIR ayrı ayrı kaydedilebilir
|
|
||||||
|
|
||||||
## Compiling Session
|
|
||||||
|
|
||||||
AST ağacını IRye dönüştürürken neleri aktaracağı derleyici parametre şeklinde verilebilir.
|
|
||||||
IR, yanlızca JIT ve Compiling modunda değiştirilebilir. Interpreter modunda değiştirilmesine izin verilmez
|
|
||||||
IR olarak tipleme, sınıflar, değişken isimleri, tekrarlama kayıtları, işlemler ve statementlerin hangilerinin eklenebileceği değiştirilebilir
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue