saqut-compiler/docs/sonnet-handoff.md

187 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Sonnet Uygulama Promptu — Bileşik Tipler Runtime'ı (ADR-020…024)
> Bu dosya bir **devir teslim promptu**. Opus ile yapılan mimari oturumda 5 karar
> alındı (ADR-020…024). Bu plan o kararları **koda döker.** Kararları yeniden
> sorma — uygula. İletişim Türkçe; commit sonu `Co-Authored-By: Claude Opus 4.8
> <noreply@anthropic.com>`; dal `0.1.0`.
---
## 0. Nerede kaldık (bağlam)
Bu oturumda kilitlenen mimari kararlar (tümü `docs/adr-frontend-analiz.md`):
| ADR | Karar (özet) |
|---|---|
| **020** | Primitive (`int`/`float`/`bool`) = **değer**; bileşik (`struct`/`array`/`string`) = **referans** (JS/Java/C# modeli). "Pointer yok" = kullanıcıya `&`/`*` *sözdizimi* yok; runtime referansı kullanır. |
| **021** | Null güvenliği: varsayılan **non-null**; nullable açıkça `Type?`. Akış-duyarlı null analizi (compile-time, runtime sıfır). `a!` = runtime-kontrollü iddia. |
| **022** | GC: basit **taşımasız, stop-the-world, deterministik mark-sweep**. Nesne modeli **baştan GC-hazır** (header + kök sayımı + çocuk sayımı). v1: toplama YOK. **`shared_ptr`'ı kalıcı sahiplik modeli YAPMA.** |
| **023** | `==`: primitive değer; referans (struct/array) **kimlik** (aynı nesne); string **içerik**. Derin eşitlik asla `==`'e bağlanmaz → ayrı `deepEquals()`. |
| **024** | String = **immutable değer-tipi, iç temsil UTF-8**. `s+"x"` yeni string üretir; `==` içerik. |
ık mimari borç: **#56** (döngüsel referans → mark-sweep GC v2). Şimdilik toplama yok, bilinçli.
**Mevcut kod durumu:**
- int-only pipeline uçtan uca çalışıyor (`examples/fibonacci.sqt`).
- `src/vm/value.hpp``Value` = `{ ValueKind kind; int intValue; std::string stringValue; }`. String **inline** (immutable olduğu için yeterli — taşıma zorunlu değil).
- `src/ir/` → 3-adresli IR, slot tabanlı. `instruction.hpp`, `ir_generator.cpp`, `ir_program.hpp`.
- `src/vm/interpreter.cpp` → bytecode yorumlayıcı döngü. `call_frame.hpp` çağrı çerçevesi.
- struct/array: parser + semantik **var**, IR/VM codegen **YOK**.
---
## 1. İlk görev — GC-hazır nesne modeli + ARRAY runtime (dikey dilim)
**Neden array, string değil:** string zaten immutable-değer olarak inline çalışıyor;
asıl kararları (referans semantiği + GC-hazır nesne modeli + kimlik eşitliği)
**doğrulayan** ilk gerçek referans-tipi array'dir. Bu görev, struct'ın da oturacağı
temeli atar.
### KAPSAM DIŞI (bu görevde YAPMA — sonraki görevler)
- ❌ Gerçek çöp toplama (mark-sweep). ADR-022 v1 = toplama yok. Sadece header +
all-objects listesi + kök-sayımı *kancasını* kur.
- ❌ Tam null akış-analizi (ADR-021). `int[]?` parse edilebilir ama flow-narrowing
bu görevde değil.
- ❌ struct codegen, string UTF-8 cilası, builder. Ayrı görevler (Bölüm 2).
-`shared_ptr` ile nesne sahipliği. Düz `Object*` + intrusive liste.
### Adım 1.1 — Nesne modeli temeli (`src/vm/object.hpp` veya benzeri)
```cpp
enum class ObjectType { Array /*, Struct, String (ileride) */ };
struct Object {
ObjectType type;
bool marked = false; // mark-sweep için (v2); şimdilik kullanılmaz
Object* next = nullptr; // intrusive "tüm nesneler" listesi (mark-sweep tarayışı için)
};
```
- Bir **Heap/allocator**: `Object* allocate(...)` her yeni nesneyi `next` zincirine
ekler. **Free yok** (v1). Yıkıcıda/process exit'te toptan bırak.
- **Kök sayımı kancası:** VM'in operand stack + frame local'leri + global slot'lar
üstünden referansları gezebileceği bir yol bırak (şimdilik imza/TODO yeterli; içini
doldurmak v2). `// TODO(#56): mark-sweep kök taraması buradan` ile işaretle.
### Adım 1.2 — `Value`'yu referans taşıyacak şekilde genişlet (`src/vm/value.hpp`)
- `ValueKind`'a `Ref` ekle (array/struct nesnelerine `Object*`).
- `Value`'ya `Object* ref = nullptr;` alanı + `static Value fromRef(Object*)`.
- `Nil` kind ekle (ADR-021 null: `Type?` null değeri ve referans varsayılanı).
- `isTruthy`/`toString`/`typeName`'i yeni kind'lar için genişlet.
- String inline kalsın (`ValueKind::String`), dokunma.
### Adım 1.3 — ArrayObject
```cpp
struct ArrayObject : Object { // type = ObjectType::Array
std::vector<Value> elements; // homojen (int[] → hepsi Int)
};
```
- Array literali (`[1,2,3]` — **parser'ın mevcut sözdizimini doğrula**, Bölüm 4'e bak)
→ ArrayObject tahsis, `elements` doldur, `Value::fromRef` ile slot'a koy.
### Adım 1.4 — IR opcode'ları + IR üreteci
- `ARRAY_NEW` (literal/boyuttan array oluştur), `ARRAY_GET dest, arr, idx`,
`ARRAY_SET arr, idx, val`, `ARRAY_LEN dest, arr`. (`instruction.hpp` + üreteç.)
- **Referans semantiği:** array bir fonksiyona geçince/atanınca `Value` (içindeki
`Object*`) **kopyalanır ama nesne paylaşılır**`func(arr)` içindeki `ARRAY_SET`
çağıranı etkiler. (Bu, kararın doğrulandığı kritik testtir.)
- **`==` (ADR-023):** array'de **kimlik** → iki `Value`'nun `ref`'i aynı `Object*` mı?
(İçerik DEĞİL.) Mevcut EQ opcode'unu tip-bazlı dallandır veya `REF_EQ` ekle.
### Adım 1.5 — Sınır kontrolü (kafes felsefesi)
- `ARRAY_GET`/`ARRAY_SET` index sınır dışıysa → **temiz runtime hatası** (sessiz UB
değil). saQut "cage" — koruma şart.
### Doğrulama (golden test — `tests/` veya `examples/`)
```c
func degistir(int[] a) {
a[0] = 99;
}
func main() {
int[] x = [1, 2, 3];
degistir(x);
print(x[0]); // 99 ← referans semantiği (ADR-020)
int[] y = x;
print(y == x); // true ← kimlik (aynı nesne, ADR-023)
int[] z = [1, 2, 3];
print(z == x); // false ← içerikçe aynı ama farklı nesne
print(x[1]); // 2
// x[5] → runtime sınır hatası
}
```
`saqut run` ile beklenen çıktı doğrulanmalı. `saqut ir` çıktısı yeni opcode'ları göstermeli.
---
## 2. Sonraki görevler (sıralı — ilk görev bitince)
1. **Struct runtime.** Alanlar (isimli), `StructObject : Object { std::vector<Value> fields; }`.
`struct Node { Node next; }` artık **meşru** (referans → sonlu boyut). **E010
revizyonu:** referansla tutulan struct alanı için döngü artık hata DEĞİL (ADR-020).
Bu görev #56'yı *canlı* hale getirir (döngü kurulabilir, henüz toplanmaz).
2. **String cilası (ADR-024).** İçerik `==`'i doğrula; UTF-8 çok-baytlı pass-through
(`"şğü"` concat+print bozulmasın); bayt-uzunluğu vs karakter ayrımınıık API
olarak işaretle. (İstege bağlı: string'i de Object modeline taşıyıp intern et —
zorunlu değil.)
3. **Null akış-analizi (ADR-021 — REVİZE).** Ayrı **frontend** görevi: `Type?` tip
sistemi + `T <: T?` atama kuralı + katı operand kuralı + akış-duyarlı narrowing
(nested `if` + sıralı guard + `&&`). ⚠️ **`a!`/`??`/`?.` YASAK** — null yalnızca
görünür `if` ile aklanır. `T?` üstünde doğrudan erişim → derleme hatası. Frontend
kesin çözer (backend yeniden analiz etmez). Detay: TODO Bölüm "SIRADAKİ İŞ" + ADR-021.
4. **Hata yönetimi (ADR-025, #57).** Struct-tabanlı yakalanabilir hata (Swift-tarzı):
- **Önkoşul:** IR'a **satır tablosu** (komut index → kaynak konum) — stacktrace için. Şu an taşıyor mu doğrula.
- Standart built-in `struct Error { int line; int char; string message; string trace; string code; }`.
- Klasik **`try { ... } catch (e) { ... }` bloğu** (unwind + en yakın handler'a zıpla); `catch (e)``e : Error`. `throw` ile kullanıcı da kaldırır.
- Runtime null-deref (NPE analoğu), array OOB, /0, `a!` patlaması**yakalanabilir hata**; `message`/`code` = derleyicinin W/E kataloğu.
- **UNCHECKED (Java/C#/JS usulü):** fonksiyon **işaretlenmez** (`noexcept`/`constexpr` tarzı YOK), çağrıda **`try f()` YOK**. İmza-işaretli Swift/Zig modeli KULLANMA.
- Stacktrace = frame stack'ten en içten dışa; insan + JSON; deterministik (adım indeksi/replay handle).
5. **float/double (#44).** Bağımsız; `Value::Float` + FADD… opcode + tip denetleyici.
6. **mark-sweep GC v2 (#56).** Adım 1.1'de bırakılan header+kök kancası üstünde aç.
---
## 3. Uyman gereken kararlar (sorma, uygula)
- Referans semantiği: bileşik = paylaşılan nesne; primitive = kopya (ADR-020).
- Array/struct `==` = **kimlik**; string `==` = **içerik** (ADR-023).
- Nesne modeli GC-hazır ama v1 toplama YOK (ADR-022); `shared_ptr` sahiplik modeli kurma.
- Sınır kontrolü + temiz runtime hataları (kafes felsefesi).
- Erken soyutlama yok: önce çalışan dikey dilim, framework sonra (CLAUDE.md ilkesi).
## 4. Bloklamayan açık noktalar (ilk göreve engel değil — gerekirse Opus'a sor)
- **Array literal sözdizimi:** parser'da `[1,2,3]` mi `{0,1,2}` mi kabul ediliyor?
Mevcut parser'ı **doğrula**; tutarsızsa `[...]` tercih (tip `int[]`). Karar gerekirse işaretle.
- Array sabit-boyut mu büyüyebilir mi: readme "dinamik" der; ilk görevde literal+indeks
yeter, büyütme API'si (`push`/`len`) sonra.
- `int[]` non-null varsayılan (ADR-021) → `int[] a;` init zorunlu; nullable `int[]?`.
- #42 (cast modeli) ve #41 (stdlib politikası) henüz karara bağlanmadı — ilk görevi
bloklamaz; sıraları gelince Opus ile.
---
## 5. Özet — tek cümle
GC-hazır basit nesne modelini kur (header + all-objects listesi, toplama yok), `Value`'ya
referans (`Ref`) + `Null` ekle, **array**'i referans semantiği + kimlik `==` + sınır
kontrolüyle uçtan uca çalıştır; struct ve null-analizi sonraki görevler.
---
## 6. ⚠️ TERMİNOLOJİ KİLİDİ — isimleri değiştirme/icat etme
Bu oturumda `null` yerine `nil` yazıldı; bu tür sapmalar **olmamalı.** Anlaşılan
isimler **aynen** kullanılır. İsmi belirsiz bir şeyle karşılaşırsan **icat etme —
Opus'a sor.**
| Kavram | DOĞRU | YANLIŞ (kullanma) |
|---|---|---|
| Null anahtar sözcüğü / literal | **`null`** | ~~`nil`~~, ~~`none`~~, ~~`void`~~ |
| Nullable tip işareti | **`Type?`** (ör. `int?`, `Node?`) | ~~`Optional<T>`~~, ~~`Type \| null`~~ |
| Non-null iddiası / elvis / safe-call | **YASAK**`if` narrowing kullan | ~~`a!`~~, ~~`a ?? x`~~, ~~`a?.f`~~ (ADR-021 revize) |
| Array literal | **`[1, 2, 3]`** | ~~`{1,2,3}`~~ |
| Array tip | **`int[]`** | ~~`array<int>`~~, ~~`[]int`~~ |
| Hata tipi | **`Error`** (`{line,char,message,trace,code}`) | ~~`Exception`~~, ~~`Err`~~ |
| Hata kaldırma / yakalama | **`throw` / `try` / `catch`** | ~~`raise`~~, ~~`rescue`~~ |
| Fonksiyon | **`func`** | ~~`fn`~~, ~~`function`~~, ~~`def`~~ |
| C++ ValueKind null'u | **`ValueKind::Null`** | ~~`Nil`~~ |
**Genel kural:** ADR'lerde/handoff'ta yazan tam ismi kullan. Yeni bir isim gerekiyorsa
ve ADR'de yoksa, **kendin karar verme** — TODO'ya not düş veya Opus'a sor. Kod
identifier'ları İngilizce (dil sözdizimi), yorum/commit Türkçe.