Merge pull request 'feat: ADR-024/025/021 — string concat, try/catch/throw, nullable akış-analizi' (#115) from 0.1.0 into master

This commit is contained in:
saqut 2026-06-20 21:36:43 +03:00
commit fe8d73a13c
123 changed files with 4584 additions and 602 deletions

4
.gitignore vendored
View File

@ -17,6 +17,4 @@ scripts/gitea.py
__pycache__/ __pycache__/
# CMake versiyona özgü dosyalar (otomatik üretilir, her güncellemede değişir) # CMake versiyona özgü dosyalar (otomatik üretilir, her güncellemede değişir)
build/CMakeFiles/[0-9]*/ build/*
build/.cmake/
build/compile_commands.json

View File

@ -20,37 +20,95 @@ git'te izlenir.
ham hız değil). C'ye transpile ileride geçerli 2. backend. İleride makine kodu ham hız değil). C'ye transpile ileride geçerli 2. backend. İleride makine kodu
gerekirse libgccjit/LLVM'e bağlanılır (çok uzak). Bellek = host C++ heap; özel gerekirse libgccjit/LLVM'e bağlanılır (çok uzak). Bellek = host C++ heap; özel
allocator yok. (ADR-015) allocator yok. (ADR-015)
- **Dil kimliği:** prosedürel, C-ailesi sözdizimi, value semantics, zorunlu - **Dil kimliği:** prosedürel, C-ailesi sözdizimi, zorunlu class/main boilerplate
class/main boilerplate yok. **Yok:** class/OOP, closure, generic, kullanıcı yok. **Semantik (ADR-020):** primitive (`int`/`float`/`bool`) = **değer**;
pointer'ı (`*`/`&`), auto/tip çıkarımı, gizli int↔float (tek istisna sabit bileşik (`struct`/`array`/`string`) = **referans** (JS/Java/C# modeli). "Pointer
folding). **Var:** struct, tipli fonksiyonlar, array (`int[]`). `interface` yok" = kullanıcıya `&`/`*` **sözdizimi** verilmez; derleyici/runtime içeride ve
**ertelendi** (reddedilmedi, ADR-018). çalışma zamanında referansı sonuna kadar kullanır. **Yok:** OOP, closure,
generic, auto/tip çıkarımı, gizli int↔float (tek istisna sabit folding). **Var:**
struct, tipli fonksiyonlar, array (`int[]`). `class`/`function` sözdizimsel
**rezerve** (semantik ileride). `interface` **ertelendi** (ADR-018).
⚠️ Referans semantiği döngüsel-referans **sızıntısını** açtı → GC/döngü
toplayıcı borcu (**#56**, `karar-gerekli`).
- **Null güvenliği (ADR-021, REVİZE):** varsayılan non-null; nullable açıkça `Type?`
(Kotlin/Swift). `null` yalnızca `T?`'ye atanır; `T?` üstünde doğrudan erişim derleme
hatası. **Atama kuralı `T <: T?`** (notnull→nullable serbest, nullable→notnull yasak).
**Katı operand kuralı:** non-null bağlamda her operand statik non-null olmalı
(`int a=b+c+d`, biri nullable → hata). Aklama **yalnızca görünür `if` narrowing**
(nested + sıralı guard + `&&`; alias takibi yok). ⚠️ **`a!`/`??`/`?.` YASAK** (gizli
runtime null-aklama yok). Runtime maliyeti **sıfır**; frontend kesin çözer (backend
yeniden analiz etmez) → runtime null-deref esasen FFI backstop'u. SSA gerekmez (#2).
- **Bellek/GC (ADR-022):** **basit, taşımasız, stop-the-world, deterministik
mark-sweep** (döngüleri toplar, "cage" korunur). **`shared_ptr`'ı kalıcı model
YAPMA** (refcount döngüde sızar = topuğa-sıkma). Kural: nesne modelini **baştan
GC-hazır** kur (header: tip+mark biti+liste; VM kök sayar; nesne çocuk
referansları sayar). v1: toplamasız (arena); v2: aynı model üstünde mark-sweep.
Asıl perf-katili GC kararı → basit tutarak de-risk edildi.
- **Eşitlik (ADR-023):** `==` primitive'de değer, referans (struct/array) **kimlik**
(aynı nesne). Derin/yapısal eşitlik **asla** `==`'e bağlanmaz → ayrı görünür
`deepEquals()` (PHP `==`/`===`/`clone` ailesi gibi). **String istisnası:** `==`
**içerik** olmalı (Java gotcha'sından kaçın) → string'i immutable değer-tipi
modelle (#40). `obj==obj`'i hata yapmak + kullanıcı-tanımlı eşitlik = uzak gelecek.
- **String (ADR-024):** **immutable değer-tipi, iç temsil UTF-8.** `s = s + "x"`
yeni string üretir; `==` içerik (ADR-023). Bayt/scalar/grapheme erişimi açıkça
ayrı (sahte O(1) karakter indeksi YOK). Verimli birleştirme için ileride builder.
Çözdüğü: #40 (yüzey), #9 (iç temsil). Mevcut `Value` string'i inline tutuyor —
immutable olduğu için bu yeterli; heap/object-model'e taşımak zorunlu değil.
- **Hata yönetimi (ADR-025, #57):** **Swift-tarzı** yakalanabilir, **struct-tabanlı**
hata — OOP/extend YOK. Standart `Error { line; char; message; trace; code }`
(message=W/E metni, code=W/E kodu). **Klasik `try{}catch{}` bloğu, UNCHECKED**
(Java/C#/JS usulü): fonksiyon işaretlenmez (`noexcept`/`constexpr` tarzı YOK),
çağrıda `try f()` yok — developer'a güven, alışkanlık bozulmaz. Runtime null-deref
(NPE analoğu), array OOB, /0, `a!` patlaması → yakalanabilir hata (ADR-021'in runtime
backstop'u). `throw` ile kullanıcı da kaldırır. Deterministik stacktrace (IR satır
tablosu önkoşul). **Tuple → ertelendi** (ADR-014'teki "yok" gevşedi). `finally` yerine
ileride `defer`.
- **Tip dönüşümü (ADR-026, #42):**ık **`as`** (infix, sola-bağlı): `x as int`.
Yalnızca **skaler + string** arası; **struct/array cast YOK** (elle yapıcı fonksiyon —
derleyiciyi sade tutar, sessiz alan kaybı önlenir). Başarısızlık **hedef tipin
nullable'lığıyla:** `as int``Error` fırlatır; `as int?``null`. Ayrı `as?` YOK.
`float→int` sıfıra kırpar (NaN/Inf/taşma fallible). `int(x)` fonksiyon-stili reddedildi.
- **Analiz vs Optimizasyon:** Analiz orijinal AST üstünde annotation; optimizasyon - **Analiz vs Optimizasyon:** Analiz orijinal AST üstünde annotation; optimizasyon
**klon** üstünde dönüşüm. `ASTNode::clone()` yük taşıyan merkezi bileşen **klon** üstünde dönüşüm. `ASTNode::clone()` yük taşıyan merkezi bileşen
(parent pointer'lar + sembol tablosu remap edilir, ADR-007). Fixpoint döngüsü + (parent pointer'lar + sembol tablosu remap edilir, ADR-007). Fixpoint döngüsü +
iterasyon tavanı (`maxFixpointRounds`, ADR-009). iterasyon tavanı (`maxFixpointRounds`, ADR-009).
- **Literal/tip kuralı:** tamsayı literali bağlama-göre tiplenir (`float x = 1;` - **Literal/tip kuralı:** tamsayı literali bağlama-göre tiplenir (`float x = 1;`
geçerli; `int y = 1.5;`→E003; değişken→değişken gizli dönüşüm yok). Döngüsel geçerli; `int y = 1.5;`→E003; değişken→değişken gizli dönüşüm yok). Döngüsel
by-value struct → E010. (ADR-010/011) by-value struct → E010 (⚠️ ADR-020 ile revize: referansla tutulan struct alanı
artık döngü kurabilir, `Node next` meşru). (ADR-010/011)
- **FFI seam:** kasıtlı "host fonksiyonu çağır" mekanizması (`callhost`); `print` - **FFI seam:** kasıtlı "host fonksiyonu çağır" mekanizması (`callhost`); `print`
ilk müşteri (ADR-016). Batteries = sınır/FFI problemi, "zlib'i yeniden yaz" ilk müşteri (ADR-016). Batteries = sınır/FFI problemi, "zlib'i yeniden yaz"
değil; kripto asla elle yazılmaz (ADR-017). değil; kripto asla elle yazılmaz (ADR-017).
## Mevcut durum (yapılan vs planlanan) ## Mevcut durum (yapılan vs planlanan)
- **Çalışıyor:** lexer, tokenizer, Pratt parser, AST, AST'nin JSON serileştirmesi, - **✅ Birinci kilometre taşı AŞILDI:** `examples/fibonacci.sqt`
CLI iskeleti (`tokens`/`ast`/`symbols`/`run`), konum takibi, basit aritmetiği (recursive + iterative) `saqut run` ile çalışıyor → `55\n55`.
düşüren minimal IR deneyi. - **Çalışıyor (tam pipeline):**
- **Planlı (henüz YOK):** sembol tablosu, semantik analiz, tip sistemi, diagnostic - Lexer, tokenizer, Pratt parser, AST + JSON serileştirmesi
motoru, optimizasyon, IR+bytecode VM ile çalıştırma. - Sembol tablosu (iki-geçişli toplayıcı, döngüsel struct tespiti)
- **Birinci kilometre taşı ("bitti" tanımı):** `examples/fibonacci.sqt` - Tip sistemi (`src/core/type.hpp`) + diagnostic motoru (`src/diagnostic/`)
(recursive + iterative) derlenip çalıştırılabilmeli. - Tip denetleyici + yapısal doğrulayıcı (`src/semantic/`)
- Optimizasyon: constant folding (int/bool/logical) + dead code elimination
- IR üreteci (3-adresli, slot tabanlı) + bytecode VM (yorumlayıcı döngü)
- CLI: `tokens` / `ast` / `symbols` / `check` / `ir` / `run` (6 komut)
- **Henüz YOK (bilinen eksikler):**
- float/double codegen (tip sistemi var, IR opcode'u yok)
- struct IR (parse/semantik var, codegen yok)
- array IR (parse/semantik var, codegen yok)
- `%=` operatörü IR'da eksik (#37)
- Global değişken IR üretimi sessizce atlıyor (#38)
- W003 ölü kod uyarısı üretilmiyor (#36)
- DCE silinen düğümleri `delete` etmiyor — bellek sızıntısı (#35)
- **İlke:** Önce uçtan uca tek **dikey dilim**, sonra çerçeve. Erken soyutlamadan kaçın. - **İlke:** Önce uçtan uca tek **dikey dilim**, sonra çerçeve. Erken soyutlamadan kaçın.
## Belge haritası ## Belge haritası
- `readme.md` — toolbox çerçevesi, built-vs-planned, dil kimliği, çalıştırma modeli. - `readme.md` — toolbox çerçevesi, built-vs-planned, dil kimliği, çalıştırma modeli.
- `docs/fikirler.md` — ADR-001…005 (backend stratejisi, parser, header-only, token, IR). - `docs/fikirler.md` — ADR-001…005 (backend stratejisi, parser, header-only, token, IR).
- `docs/adr-frontend-analiz.md` — ADR-006…019 (frontend, analiz/optimizasyon, - `docs/adr-frontend-analiz.md` — ADR-006…026 (frontend, analiz/optimizasyon,
çalıştırma modeli, FFI, interface, bellek). çalıştırma modeli, FFI, interface, bellek, **değer/referans semantiği, null
güvenliği, mark-sweep GC, eşitlik, string, hata yönetimi, tip dönüşümü**).
- `docs/sonnet-handoff.md`**Sonnet için uygulama promptu** (ADR-020…024'ü koda
döken sıralı görev planı; ilk görev: GC-hazır nesne modeli + array runtime).
- `docs/roadmap-frontend.md` — faz-faz uygulama planı (Faz 04 → fibonacci). - `docs/roadmap-frontend.md` — faz-faz uygulama planı (Faz 04 → fibonacci).
- `docs/transkript-frontend-tasarim.md` — tasarım oturumu transkripti. - `docs/transkript-frontend-tasarim.md` — tasarım oturumu transkripti.
- `examples/fibonacci.sqt` — geçerli referans program. - `examples/fibonacci.sqt` — geçerli referans program.
@ -97,6 +155,6 @@ git'te izlenir.
## Çalışma konvansiyonları ## Çalışma konvansiyonları
- Commit mesajları sonunda: `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`. - Commit mesajları sonunda: `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`.
- Ana dal `master`; commit/push kullanıcı isteyince yapılır. - Ana dal `0.1.0`; `master` branch yok. commit/push kullanıcı isteyince yapılır.
- Wiki API'si Gitea'da REST üzerinden çalışmadı; wiki içeriği `wiki.md`'ye yazılıp - Wiki API'si Gitea'da REST üzerinden çalışmadı; wiki içeriği `wiki.md`'ye yazılıp
kullanıcı tarafından elle yapıştırılıyor. kullanıcı tarafından elle yapıştırılıyor.

View File

@ -20,3 +20,99 @@ file(GLOB_RECURSE SOURCES "src/*.cpp")
add_executable(saqut ${SOURCES}) add_executable(saqut ${SOURCES})
target_include_directories(saqut PRIVATE src) target_include_directories(saqut PRIVATE src)
# Testler
enable_testing()
set(SAQUT_BINARY "${CMAKE_BINARY_DIR}/saqut")
set(GOLDEN_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/run_golden.cmake")
# Birim testleri (tests/run.sh)
add_test(
NAME unit_tests
COMMAND bash "${CMAKE_SOURCE_DIR}/tests/run.sh"
)
# Golden testleri tests/golden/**/*.sqt dosyalarını otomatik keşfet.
# Her .sqt için iki olası expected dosyası kontrol edilir:
# BASE.expected saqut run (siyah-kutu çıktı testi)
# BASE.ir_opt.expected saqut ir --optimized (beyaz-kutu IR testi)
file(GLOB_RECURSE ALL_GOLDEN_SQT CONFIGURE_DEPENDS
"${CMAKE_SOURCE_DIR}/tests/golden/*.sqt"
)
foreach(SQT_FILE ${ALL_GOLDEN_SQT})
file(RELATIVE_PATH REL "${CMAKE_SOURCE_DIR}/tests/golden" "${SQT_FILE}")
string(REPLACE ".sqt" "" BASE "${REL}")
string(REPLACE "/" "_" TNAME "${BASE}")
# Siyah-kutu: saqut run çıktısı
set(RUN_EXPECTED "${CMAKE_SOURCE_DIR}/tests/golden/${BASE}.expected")
if(EXISTS "${RUN_EXPECTED}")
add_test(
NAME "golden_${TNAME}"
COMMAND ${CMAKE_COMMAND}
-DBINARY=${SAQUT_BINARY}
-DSOURCE=${SQT_FILE}
-DEXPECTED=${RUN_EXPECTED}
-P "${GOLDEN_SCRIPT}"
)
endif()
# Beyaz-kutu: saqut ir --optimized çıktısı
set(IR_OPT_EXPECTED "${CMAKE_SOURCE_DIR}/tests/golden/${BASE}.ir_opt.expected")
if(EXISTS "${IR_OPT_EXPECTED}")
add_test(
NAME "golden_${TNAME}_ir_opt"
COMMAND ${CMAKE_COMMAND}
-DBINARY=${SAQUT_BINARY}
-DSOURCE=${SQT_FILE}
-DEXPECTED=${IR_OPT_EXPECTED}
-DCOMMAND=ir
-DOPTIMIZED=1
-P "${GOLDEN_SCRIPT}"
)
endif()
# Doğruluk kalkanı: saqut run --optimized çıktısı == beklenen golden değer
# "Optimizasyon oldu" değil, "optimize IR doğru sonuç verdi" testleri.
set(RUN_OPT_EXPECTED "${CMAKE_SOURCE_DIR}/tests/golden/${BASE}.run_opt.expected")
if(EXISTS "${RUN_OPT_EXPECTED}")
add_test(
NAME "golden_${TNAME}_run_opt"
COMMAND ${CMAKE_COMMAND}
-DBINARY=${SAQUT_BINARY}
-DSOURCE=${SQT_FILE}
-DEXPECTED=${RUN_OPT_EXPECTED}
-DOPTIMIZED=1
-P "${GOLDEN_SCRIPT}"
)
endif()
# Negatif test: .compile_error derleme hatası beklenen golden testler.
# Dosya içeriği stderr'de aranır (regex/düz dize).
set(COMPILE_ERROR_EXPECTED "${CMAKE_SOURCE_DIR}/tests/golden/${BASE}.compile_error")
if(EXISTS "${COMPILE_ERROR_EXPECTED}")
add_test(
NAME "golden_${TNAME}_compile_error"
COMMAND ${CMAKE_COMMAND}
-DBINARY=${SAQUT_BINARY}
-DSOURCE=${SQT_FILE}
-DEXPECTED=${COMPILE_ERROR_EXPECTED}
-P "${CMAKE_SOURCE_DIR}/cmake/run_golden_error.cmake"
)
endif()
# Negatif test: .runtime_error çalışma zamanı hatası beklenen golden testler.
# Aynı altyapı: exit code != 0 + stderr içeriği kontrolü.
set(RUNTIME_ERROR_EXPECTED "${CMAKE_SOURCE_DIR}/tests/golden/${BASE}.runtime_error")
if(EXISTS "${RUNTIME_ERROR_EXPECTED}")
add_test(
NAME "golden_${TNAME}_runtime_error"
COMMAND ${CMAKE_COMMAND}
-DBINARY=${SAQUT_BINARY}
-DSOURCE=${SQT_FILE}
-DEXPECTED=${RUNTIME_ERROR_EXPECTED}
-P "${CMAKE_SOURCE_DIR}/cmake/run_golden_error.cmake"
)
endif()
endforeach()

139
TODO.md Normal file
View File

@ -0,0 +1,139 @@
# TODO — Teknik Borçlar ve Ertelenen Kararlar
Bu dosya, kasıtlı olarak ertelenen teknik kararları ve ileride ele alınması gereken
tasarım noktalarını tutar. Her giriş hangi issue'ya bağlı olduğunu belirtir.
---
## ✅ TAMAMLANDI — GC-hazır nesne modeli + array runtime (2026-06-20)
ADR-020…024 (değer/referans semantiği, null güvenliği, mark-sweep GC, eşitlik)
doğrultusunda uçtan uca array çalışıyor:
- `src/vm/object.hpp` — Object, ArrayObject, Heap (v1: toplama yok, GC-hazır header)
- `src/vm/value.hpp` — ValueKind::Ref + Null eklendi (dil anahtar sözcüğü `null`, `nil` DEĞİL)
- `src/ir/instruction.hpp` — ARRAY_NEW/GET/SET/LEN eklendi
- Array literal parser (`[1,2,3]`), `int[]` tip sözdizimi (Java/C# stili)
- Referans semantiği, kimlik `==` (ADR-023), sınır kontrolü
- Golden test: `tests/golden/array/ref_semantics.sqt`
## ✅ TAMAMLANDI — Struct runtime + E010 revizyonu (2026-06-20)
ADR-020 doğrultusunda struct referans semantiğiyle uçtan uca çalışıyor:
- `src/vm/object.hpp` — StructObject : Object, alan erişimi (GC-hazır header)
- `src/vm/value.hpp` — ValueKind::Null eklendi (dil anahtar sözcüğü `null`)
- E010 revizyonu: referansla tutulan `struct Node { Node next; }` artık meşru
(döngü kurulabilir, GC v2 ile toplanacak)
## ✅ TAMAMLANDI — float/double aritmetik runtime (#44) (2026-06-20)
- `src/vm/value.hpp` — ValueKind::Float + floatValue alanı
- IR opcode'ları: FADD/FSUB/FMUL/FDIV + float karşılaştırma
- Literal bağlama-göre tipleme korundu (sabit folding dahil)
## ✅ TAMAMLANDI — String cilası (ADR-024) (2026-06-20)
- `src/core/type.hpp``isString()` yüklem yardımcısı eklendi
- `src/ir/instruction.hpp``STRING_CONCAT` opcode eklendi
- `src/semantic/type_checker.cpp``+` string için izin (her iki taraf `string` → sonuç `string`)
- `src/ir/ir_generator.cpp``generateBinaryArithmetic` string tespiti: `ADD``STRING_CONCAT`; `+=` için de `STRING_CONCAT`
- `src/vm/interpreter.cpp``STRING_CONCAT` case: `stringValue + stringValue`
- `tests/golden/string/concat.sqt` — concat, `+=`, içerik `==` golden testi
- İçerik `==` / `!=` VM'de zaten vardı (ADR-023/024); `print(string)` zaten çalışıyordu
## ✅ TAMAMLANDI — Hata yönetimi (ADR-025, #57) (2026-06-20)
- `src/parser/ast_node.hpp``TryStatement`, `ThrowStatement` ASTKind eklendi
- `src/parser/nodes/statements.hpp/.cpp``TryStatementNode`, `ThrowStatementNode`
- `src/parser/parser_base.hpp` + `parser.cpp``parseTryStatement()`, `parseThrowStatement()`
- `src/ir/instruction.hpp``ENTER_TRY`, `LEAVE_TRY`, `THROW` opcode'ları
- `src/ir/ir_generator.cpp` — try/catch/throw IR üretimi
- `src/vm/interpreter.hpp``TryFrame` struct, `tryStack_`, `pendingThrow_`, `makeErrorValue()`
- `src/vm/interpreter.cpp` — ENTER_TRY/LEAVE_TRY/THROW VM uygulaması; runtime hataları
(DIV/0, array OOB) `pendingThrow_` üzerinden Error nesnesi olarak yakalanabilir hale getirildi
- `src/symbol/symbol_collector.cpp``Error` builtin struct kaydı (alan sırası: line,col,message,trace,code)
- `src/semantic/type_checker.cpp` — TryStatement/ThrowStatement tip kontrolü (unchecked)
- `tests/golden/error/basic_catch.sqt` — sıfıra bölme yakalama
- `tests/golden/error/throw_and_nested.sqt` — iç içe fonksiyon unwind + array OOB + throw
- **Not:** IR satır tablosu (stacktrace doldurma) ertelendi — trace alanı boş kalıyor
## ✅ TAMAMLANDI — Null akış-analizi (ADR-021) (2026-06-20)
- `src/core/type.hpp``bool nullable` alanı; `asNullable()`, `asNonNull()`, `equalsBase()`, `isNullLiteral()` yardımcıları; `fromName("int?")` desteği; `toString()``int?`
- `src/parser/parser.cpp``?` suffix ayrıştırma (değişken, parametre, dönüş tipi); dispatch'te `int? f()``parseFunctionDecl()` yönlendirmesi düzeltildi
- `src/ir/instruction.hpp``LOAD_NULL` opcode eklendi
- `src/ir/ir_generator.cpp``LiteralType::BOŞ``LOAD_NULL`
- `src/vm/interpreter.cpp``LOAD_NULL` case → `Value::null()`
- `src/semantic/type_checker.hpp``narrowedNonNull_` set; `extractNullCheck()`, `alwaysExits()` yardımcıları
- `src/semantic/type_checker.cpp`:
- `checkAssign`: `T? ← null` OK; `T ← T?` hata (E003); `T? ← T` OK (widening)
- `checkExpr Literal BOŞ`: null sentinel tipi (`Void+nullable`)
- `checkExpr Identifier`: `narrowedNonNull_`'dan non-null olduğu bilinenlerde nullable flag'i kaldırılıyor
- `checkExpr BinaryExpression`: `&&` sağ taraf narrowing; nullable operand hatası (E003)
- `checkExpr MemberAccess`: nullable nesne üstünde doğrudan erişim hatası
- `checkStmt Block`: guard pattern (`if (a == null) return;` → sonrasında `a` non-null)
- `checkStmt IfStatement`: nested narrowing (`if (a != null)` → then'de non-null, `if (a == null)` → else'de non-null)
- `tests/golden/null/narrowing.sqt` — nested + guard narrowing, `int?` dönüş tipi ✓
- `tests/golden/null/nullable_assign_error.sqt``T? → T` atama E003 ✓
- `tests/golden/null/nullable_operand_error.sqt` — nullable aritmetik operand E003 ✓
- `tests/golden/null/and_narrowing.sqt``&&` sağ taraf narrowing ✓
## 🚀 SIRADAKİ İŞ
1. **mark-sweep GC v2 (#56)** — en son; özellik bloklamaz, en karmaşık. Trigger basit
"her N tahsiste" yeter; nesne modeli zaten GC-hazır.
ık mimari borçlar: **#56** (döngüsel referans → mark-sweep GC v2), **#57** (hata
modeli görünürlük alt-ekseni).
> ⚠️ **Terminoloji kilidi (Sonnet):** anlaşılan isimleri değiştirme/icat etme.
> Dil anahtar sözcüğü **`null`** (`nil` değil), array literal **`[...]`** (`{...}` değil),
> hata tipi **`Error`**. İsmi belirsizse **icat etme, Opus'a sor.** Ayrıntı:
> `docs/sonnet-handoff.md` Bölüm 6 (terminoloji kilidi).
---
## #modül-scope — IRFunction.moduleId: Modül-düzeyi değişken izolasyonu
**Etkilenen dosyalar:**
- `src/ir/instruction.hpp``LOAD_GLOBAL` / `STORE_GLOBAL` yorumları
- `src/ir/ir_program.hpp``globalCount`, `globalNames`
- `src/vm/interpreter.hpp``globalSlots_`
- `src/vm/interpreter.cpp``LOAD_GLOBAL` / `STORE_GLOBAL` case'leri
**Mevcut durum (tek dosya):**
`LOAD_GLOBAL dest, N``globalSlots_[N]` — düz vektör, tek modül varsayımı.
Tek dosyada bu doğru çalışır; `globalSlots_[0]` her zaman bu dosyanın 0. modül-değişkenidir.
**Çok modüllü derlemede yapılması gereken:**
Her `IRFunction`'a `std::string moduleId` (veya `int moduleIndex`) alanı ekle.
`Interpreter`'da `globalSlots_` yerine `std::unordered_map<std::string, std::vector<Value>> moduleSlots_` tut.
`LOAD_GLOBAL` çalışırken `frame.function->moduleId` ile doğru modülün slot alanına bak.
```
// Hedef tasarım (modül sistemi gelince):
case Opcode::LOAD_GLOBAL:
frame.slots[instr.dest] = moduleSlots_[frame.function->moduleId][instr.intValue];
break;
```
**Ne zaman:** Modül sistemi issue'ları (#3 import sözdizimi, #4 görünürlük, #5 çoklu dosya)
ele alınırken bu değişikliği de kapsama al.
---
## #sembol-modül — Symbol.sourceModule: Sembol tablosunda açık modül kimliği
**Etkilenen dosyalar:**
- `src/symbol/symbol.hpp``Symbol` struct
**Mevcut durum:**
`Symbol.definitionLoc.filePath` dosya yolunu tutuyor — modül bilgisi dolaylı olarak var.
Ama doğrudan `moduleId` / `moduleName` alanı yok; filtre/lookup için her seferinde
`definitionLoc.filePath`'i ayrıştırmak gerekir.
**Yapılması gereken:**
`Symbol` struct'ına `std::string sourceModule` alanı ekle (modül adı veya dosya yolu).
Özellikle cross-module sembol çözümleme, LSP "tanıma git" ve hata mesajlarında
"hangi modülden geldi" bilgisi için kritik.
**Ne zaman:** `#3` (import sözdizimi) veya `#4` (görünürlük) issue'larında.

Binary file not shown.

View File

@ -1,23 +1,34 @@
# ninja log v7 # ninja log v7
13 4576 1781796718440262330 CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o 20f68631dd335029 1 9 1781900092189939762 /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/cmake.verify_globs 1813c41e0f312d7e
13 4805 1781796718441539505 CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o 5fd259c0401f3e22 10 1691 1781900092199402809 CMakeFiles/saqut.dir/src/ir/ir_program.cpp.o d681b36458a6e5f5
1 2117 1781796771817437208 CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o fbabe80dcb141239 10 1957 1781900092199188672 CMakeFiles/saqut.dir/src/ir/ir_function.cpp.o 85cbc174284792d4
4580 9322 1781796723007277591 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 59cdb5935c541b26 10 5411 1781900092199511505 CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o 90eeec811f2137e6
21 6876 1781796718448262357 CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o 9313cba8d8daffed 10 5413 1781900092198939716 CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o da6f5fc90e87e6b1
16 6700 1781796718443848488 CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o e3b5b38d75fcd2ca 10 6729 1781900092199847028 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o b6c56f04a257f685
15 7814 1781796718443331391 CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o 5f5bb01381a3c3ad 15 7732 1781900092203939691 CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o 4057e3d63c63a1ab
16 7589 1781796718444498682 CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o 55743f37408c5f 10 8908 1781900092199302769 CMakeFiles/saqut.dir/src/ir/ir_generator.cpp.o 84c9f816f969cfa7
21 7502 1781796718449424977 CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o 3c8869307381c930 10 9701 1781900092199743167 CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o d2e2bb2f8a63c6d2
14 6864 1781796718442362341 CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o 5cc8b697133bcf64 1709 9770 1781900093898639567 CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o 78f2c4da7c9b2281
15 6733 1781796718442847556 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o c3d262615ede4c95 15 10364 1781900092204948414 CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o eb96bb4b1eb4ad80
1 4629 1781801148234045650 CMakeFiles/saqut.dir/src/main.cpp.o 3cfef7a665d5bf87 1957 11871 1781900094145929879 CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o ac5bbcd74d87561a
4629 4900 1781801152862380672 saqut f2e198803c4dbffb 9770 11899 1781900101958890478 CMakeFiles/saqut.dir/src/vm/interpreter.cpp.o 88078036625564ef
0 22 1781801180493522122 build.ninja 1876a59d627a585 5413 11959 1781900097601912436 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32
0 22 1781801180493522122 /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake 1876a59d627a585 10 12284 1781900092199621706 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23
6733 11112 1781796725160284765 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o ec4e483b8ddb4007 6729 13187 1781900098917905800 CMakeFiles/saqut.dir/src/semantic/structural_validator.cpp.o 4bfec8abc0e9893e
4805 9685 1781796723232278341 CMakeFiles/saqut.dir/src/semantic/structural_validator.cpp.o 248faa3675024351 5412 13356 1781900097601088348 CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o b5c20724bbf3648c
6700 10405 1781796725127284655 CMakeFiles/saqut.dir/src/semantic/type_checker.cpp.o b29c133293d988b0 7733 14099 1781900099922227854 CMakeFiles/saqut.dir/src/semantic/type_checker.cpp.o 15f44776b9c3e26d
1 850 1781801148235507662 CMakeFiles/saqut.dir/src/vm/interpreter.cpp.o b7dd80e002d68a1d 9701 14179 1781900101889890826 CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o a01677f8bb4f4dbc
2 957 1781800866770475511 CMakeFiles/saqut.dir/src/ir/ir_function.cpp.o 10f5e8dfd1461d69 8908 14635 1781900101096894819 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o 3348f498f369213d
2 718 1781800866771246136 CMakeFiles/saqut.dir/src/ir/ir_program.cpp.o 9518231d970828da 14635 14953 1781900106823866003 saqut 8f3d7184b374150b
2 3169 1781800866771136888 CMakeFiles/saqut.dir/src/ir/ir_generator.cpp.o 10a1ed4e1f52e530 2 17 1781900144964675644 /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/cmake.verify_globs 1813c41e0f312d7e
18 4193 1781900144981580253 CMakeFiles/saqut.dir/src/semantic/structural_validator.cpp.o 4bfec8abc0e9893e
18 4260 1781900144981478187 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32
18 4852 1781900144981695435 CMakeFiles/saqut.dir/src/semantic/type_checker.cpp.o 15f44776b9c3e26d
18 4914 1781900144981374397 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o b6c56f04a257f685
18 5211 1781900144980675565 CMakeFiles/saqut.dir/src/ir/ir_generator.cpp.o 84c9f816f969cfa7
18 5324 1781900144981813038 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o 3348f498f369213d
18 6912 1781900144981279910 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23
6912 7184 1781900151874641436 saqut 8f3d7184b374150b
1 8 1781900314792856660 /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/cmake.verify_globs 1813c41e0f312d7e
9 4869 1781900314800856623 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23
4869 5168 1781900319660833784 saqut 8f3d7184b374150b

View File

@ -1,4 +1,269 @@
---
events:
-
kind: "message-v1"
backtrace:
- "/usr/share/cmake-3.28/Modules/CMakeDetermineSystem.cmake:233 (message)"
- "CMakeLists.txt:2 (project)"
message: |
The system is: Linux - 6.18.5 - x86_64
-
kind: "message-v1"
backtrace:
- "/usr/share/cmake-3.28/Modules/CMakeDetermineCompilerId.cmake:17 (message)"
- "/usr/share/cmake-3.28/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)"
- "/usr/share/cmake-3.28/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)"
- "CMakeLists.txt:2 (project)"
message: |
Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
Compiler: /usr/bin/c++
Build flags:
Id flags:
The output was:
0
Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out"
The CXX compiler identification is GNU, found in:
/home/user/saqut/build/CMakeFiles/3.28.3/CompilerIdCXX/a.out
-
kind: "try_compile-v1"
backtrace:
- "/usr/share/cmake-3.28/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)"
- "/usr/share/cmake-3.28/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)"
- "CMakeLists.txt:2 (project)"
checks:
- "Detecting CXX compiler ABI info"
directories:
source: "/home/user/saqut/build/CMakeFiles/CMakeScratch/TryCompile-6ljCUz"
binary: "/home/user/saqut/build/CMakeFiles/CMakeScratch/TryCompile-6ljCUz"
cmakeVariables:
CMAKE_CXX_FLAGS: ""
CMAKE_CXX_FLAGS_DEBUG: "-g"
CMAKE_EXE_LINKER_FLAGS: ""
buildResult:
variable: "CMAKE_CXX_ABI_COMPILED"
cached: true
stdout: |
Change Dir: '/home/user/saqut/build/CMakeFiles/CMakeScratch/TryCompile-6ljCUz'
Run Build Command(s): /usr/bin/ninja -v cmTC_b1346
[1/2] /usr/bin/c++ -v -o CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.28/Modules/CMakeCXXCompilerABI.cpp
Using built-in specs.
COLLECT_GCC=/usr/bin/c++
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04.1' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04.1)
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_b1346.dir/'
/usr/libexec/gcc/x86_64-linux-gnu/13/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.28/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_b1346.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccKBrizP.s
GNU C++17 (Ubuntu 13.3.0-6ubuntu2~24.04.1) version 13.3.0 (x86_64-linux-gnu)
compiled by GNU C version 13.3.0, GMP version 6.3.0, MPFR version 4.2.1, MPC version 1.3.1, isl version isl-0.26-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/13"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/13
/usr/include/x86_64-linux-gnu/c++/13
/usr/include/c++/13/backward
/usr/lib/gcc/x86_64-linux-gnu/13/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
Compiler executable checksum: 7896445e4990772fdae9dc0659a99266
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_b1346.dir/'
as -v --64 -o CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccKBrizP.s
GNU assembler version 2.42 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.42
COMPILER_PATH=/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.'
[2/2] : && /usr/bin/c++ -v CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_b1346 && :
Using built-in specs.
COLLECT_GCC=/usr/bin/c++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04.1' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04.1)
COMPILER_PATH=/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_b1346' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_b1346.'
/usr/libexec/gcc/x86_64-linux-gnu/13/collect2 -plugin /usr/libexec/gcc/x86_64-linux-gnu/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper -plugin-opt=-fresolution=/tmp/cci1AaX8.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_b1346 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/13 -L/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/13/../../.. CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_b1346' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_b1346.'
exitCode: 0
-
kind: "message-v1"
backtrace:
- "/usr/share/cmake-3.28/Modules/CMakeDetermineCompilerABI.cmake:127 (message)"
- "/usr/share/cmake-3.28/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)"
- "CMakeLists.txt:2 (project)"
message: |
Parsed CXX implicit include dir info: rv=done
found start of include info
found start of implicit include info
add: [/usr/include/c++/13]
add: [/usr/include/x86_64-linux-gnu/c++/13]
add: [/usr/include/c++/13/backward]
add: [/usr/lib/gcc/x86_64-linux-gnu/13/include]
add: [/usr/local/include]
add: [/usr/include/x86_64-linux-gnu]
add: [/usr/include]
end of search list found
collapse include dir [/usr/include/c++/13] ==> [/usr/include/c++/13]
collapse include dir [/usr/include/x86_64-linux-gnu/c++/13] ==> [/usr/include/x86_64-linux-gnu/c++/13]
collapse include dir [/usr/include/c++/13/backward] ==> [/usr/include/c++/13/backward]
collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/13/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/13/include]
collapse include dir [/usr/local/include] ==> [/usr/local/include]
collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
collapse include dir [/usr/include] ==> [/usr/include]
implicit include dirs: [/usr/include/c++/13;/usr/include/x86_64-linux-gnu/c++/13;/usr/include/c++/13/backward;/usr/lib/gcc/x86_64-linux-gnu/13/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
-
kind: "message-v1"
backtrace:
- "/usr/share/cmake-3.28/Modules/CMakeDetermineCompilerABI.cmake:159 (message)"
- "/usr/share/cmake-3.28/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)"
- "CMakeLists.txt:2 (project)"
message: |
Parsed CXX implicit link information:
link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)]
ignore line: [Change Dir: '/home/user/saqut/build/CMakeFiles/CMakeScratch/TryCompile-6ljCUz']
ignore line: []
ignore line: [Run Build Command(s): /usr/bin/ninja -v cmTC_b1346]
ignore line: [[1/2] /usr/bin/c++ -v -o CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.28/Modules/CMakeCXXCompilerABI.cpp]
ignore line: [Using built-in specs.]
ignore line: [COLLECT_GCC=/usr/bin/c++]
ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa]
ignore line: [OFFLOAD_TARGET_DEFAULT=1]
ignore line: [Target: x86_64-linux-gnu]
ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04.1' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c ada c++ go d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2]
ignore line: [Thread model: posix]
ignore line: [Supported LTO compression algorithms: zlib zstd]
ignore line: [gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04.1) ]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_b1346.dir/']
ignore line: [ /usr/libexec/gcc/x86_64-linux-gnu/13/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.28/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_b1346.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccKBrizP.s]
ignore line: [GNU C++17 (Ubuntu 13.3.0-6ubuntu2~24.04.1) version 13.3.0 (x86_64-linux-gnu)]
ignore line: [ compiled by GNU C version 13.3.0 GMP version 6.3.0 MPFR version 4.2.1 MPC version 1.3.1 isl version isl-0.26-GMP]
ignore line: []
ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/13"]
ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed/x86_64-linux-gnu"]
ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed"]
ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"]
ignore line: [#include "..." search starts here:]
ignore line: [#include <...> search starts here:]
ignore line: [ /usr/include/c++/13]
ignore line: [ /usr/include/x86_64-linux-gnu/c++/13]
ignore line: [ /usr/include/c++/13/backward]
ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/13/include]
ignore line: [ /usr/local/include]
ignore line: [ /usr/include/x86_64-linux-gnu]
ignore line: [ /usr/include]
ignore line: [End of search list.]
ignore line: [Compiler executable checksum: 7896445e4990772fdae9dc0659a99266]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_b1346.dir/']
ignore line: [ as -v --64 -o CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccKBrizP.s]
ignore line: [GNU assembler version 2.42 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.42]
ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/]
ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../:/lib/:/usr/lib/]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.']
ignore line: [[2/2] : && /usr/bin/c++ -v CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_b1346 && :]
ignore line: [Using built-in specs.]
ignore line: [COLLECT_GCC=/usr/bin/c++]
ignore line: [COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper]
ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa]
ignore line: [OFFLOAD_TARGET_DEFAULT=1]
ignore line: [Target: x86_64-linux-gnu]
ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04.1' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c ada c++ go d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-13-EldibY/gcc-13-13.3.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2]
ignore line: [Thread model: posix]
ignore line: [Supported LTO compression algorithms: zlib zstd]
ignore line: [gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04.1) ]
ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/]
ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../:/lib/:/usr/lib/]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_b1346' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_b1346.']
link line: [ /usr/libexec/gcc/x86_64-linux-gnu/13/collect2 -plugin /usr/libexec/gcc/x86_64-linux-gnu/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper -plugin-opt=-fresolution=/tmp/cci1AaX8.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_b1346 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/13 -L/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/13/../../.. CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o]
arg [/usr/libexec/gcc/x86_64-linux-gnu/13/collect2] ==> ignore
arg [-plugin] ==> ignore
arg [/usr/libexec/gcc/x86_64-linux-gnu/13/liblto_plugin.so] ==> ignore
arg [-plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper] ==> ignore
arg [-plugin-opt=-fresolution=/tmp/cci1AaX8.res] ==> ignore
arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
arg [-plugin-opt=-pass-through=-lc] ==> ignore
arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
arg [--build-id] ==> ignore
arg [--eh-frame-hdr] ==> ignore
arg [-m] ==> ignore
arg [elf_x86_64] ==> ignore
arg [--hash-style=gnu] ==> ignore
arg [--as-needed] ==> ignore
arg [-dynamic-linker] ==> ignore
arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
arg [-pie] ==> ignore
arg [-znow] ==> ignore
arg [-zrelro] ==> ignore
arg [-o] ==> ignore
arg [cmTC_b1346] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o]
arg [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o]
arg [/usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/13] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/13]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib]
arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
arg [-L/lib/../lib] ==> dir [/lib/../lib]
arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/13/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/13/../../..]
arg [CMakeFiles/cmTC_b1346.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
arg [-lstdc++] ==> lib [stdc++]
arg [-lm] ==> lib [m]
arg [-lgcc_s] ==> lib [gcc_s]
arg [-lgcc] ==> lib [gcc]
arg [-lc] ==> lib [c]
arg [-lgcc_s] ==> lib [gcc_s]
arg [-lgcc] ==> lib [gcc]
arg [/usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o]
arg [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o]
collapse obj [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o]
collapse obj [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o]
collapse obj [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/13] ==> [/usr/lib/gcc/x86_64-linux-gnu/13]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib] ==> [/usr/lib]
collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
collapse library dir [/lib/../lib] ==> [/lib]
collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/13/../../..] ==> [/usr/lib]
implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc]
implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o]
implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/13;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
implicit fwks: []
...
--- ---
events: events:
- -
@ -113,6 +378,65 @@ events:
- "/usr/bin/site_perl" - "/usr/bin/site_perl"
- "/usr/bin/vendor_perl" - "/usr/bin/vendor_perl"
- "/usr/bin/core_perl" - "/usr/bin/core_perl"
-
kind: "find-v1"
backtrace:
- "/usr/share/cmake/Modules/CMakeDetermineCompiler.cmake:73 (find_program)"
- "/usr/share/cmake/Modules/CMakeDetermineCXXCompiler.cmake:69 (_cmake_find_compiler)"
- "CMakeLists.txt:2 (project)"
mode: "program"
variable: "CMAKE_CXX_COMPILER"
description: "CXX compiler"
settings:
SearchFramework: "NEVER"
SearchAppBundle: "NEVER"
CMAKE_FIND_USE_CMAKE_PATH: true
CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: true
CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: true
CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: true
CMAKE_FIND_USE_INSTALL_PREFIX: true
names:
- "c++"
- "CC"
- "g++"
- "aCC"
- "cl"
- "bcc"
- "xlC"
- "icpx"
- "icx"
- "clang++"
candidate_directories:
- "/home/saqut/.local/bin/"
- "/usr/local/bin/"
- "/usr/bin/"
- "/bin/"
- "/usr/local/sbin/"
- "/opt/cuda/bin/"
- "/var/lib/flatpak/exports/bin/"
- "/usr/lib/jvm/default/bin/"
- "/usr/bin/site_perl/"
- "/usr/bin/vendor_perl/"
- "/usr/bin/core_perl/"
searched_directories:
- "/home/saqut/.local/bin/c++"
- "/usr/local/bin/c++"
found: "/usr/bin/c++"
search_context:
ENV{PATH}:
- "/home/saqut/.local/bin"
- "/home/saqut/.local/bin"
- "/home/saqut/.local/bin"
- "/usr/local/bin"
- "/usr/bin"
- "/bin"
- "/usr/local/sbin"
- "/opt/cuda/bin"
- "/var/lib/flatpak/exports/bin"
- "/usr/lib/jvm/default/bin"
- "/usr/bin/site_perl"
- "/usr/bin/vendor_perl"
- "/usr/bin/core_perl"
- -
kind: "find-v1" kind: "find-v1"
backtrace: backtrace:
@ -162,7 +486,7 @@ events:
- "CMakeLists.txt:2 (project)" - "CMakeLists.txt:2 (project)"
message: | message: |
Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
Compiler: /usr/bin/g++ Compiler: /usr/bin/c++
Build flags: Build flags:
Id flags: Id flags:
@ -893,8 +1217,8 @@ events:
checks: checks:
- "Detecting CXX compiler ABI info" - "Detecting CXX compiler ABI info"
directories: directories:
source: "/home/saqut/Masa\u00fcst\u00fc/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-KRXVj0" source: "/home/saqut/Masa\u00fcst\u00fc/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-bNmRFu"
binary: "/home/saqut/Masa\u00fcst\u00fc/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-KRXVj0" binary: "/home/saqut/Masa\u00fcst\u00fc/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-bNmRFu"
cmakeVariables: cmakeVariables:
CMAKE_CXX_FLAGS: "" CMAKE_CXX_FLAGS: ""
CMAKE_CXX_FLAGS_DEBUG: "-g" CMAKE_CXX_FLAGS_DEBUG: "-g"
@ -905,19 +1229,19 @@ events:
variable: "CMAKE_CXX_ABI_COMPILED" variable: "CMAKE_CXX_ABI_COMPILED"
cached: true cached: true
stdout: | stdout: |
Change Dir: '/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-KRXVj0' Change Dir: '/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-bNmRFu'
Run Build Command(s): /usr/bin/ninja -v cmTC_aae80 Run Build Command(s): /usr/bin/ninja -v cmTC_a8847
[1/2] /usr/bin/g++ -v -o CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp [1/2] /usr/bin/c++ -v -o CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp
Using built-in specs. Using built-in specs.
COLLECT_GCC=/usr/bin/g++ COLLECT_GCC=/usr/bin/c++
Target: x86_64-pc-linux-gnu Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust,cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust,cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes
Thread model: posix Thread model: posix
Supported LTO compression algorithms: zlib zstd Supported LTO compression algorithms: zlib zstd
gcc version 16.1.1 20260430 (GCC) gcc version 16.1.1 20260430 (GCC)
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_aae80.dir/' COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a8847.dir/'
/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_aae80.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/ccmm6pzq.s /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_a8847.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/cch7GwnZ.s
GNU C++20 (GCC) version 16.1.1 20260430 (x86_64-pc-linux-gnu) GNU C++20 (GCC) version 16.1.1 20260430 (x86_64-pc-linux-gnu)
compiled by GNU C version 16.1.1 20260430, GMP version 6.3.0, MPFR version 4.2.2, MPC version 1.4.1, isl version isl-0.27-GMP compiled by GNU C version 16.1.1 20260430, GMP version 6.3.0, MPFR version 4.2.2, MPC version 1.4.1, isl version isl-0.27-GMP
@ -934,15 +1258,15 @@ events:
/usr/include /usr/include
End of search list. End of search list.
Compiler executable checksum: d47d0c990a24bc0dbaf3bd00656bd5f3 Compiler executable checksum: d47d0c990a24bc0dbaf3bd00656bd5f3
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_aae80.dir/' COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a8847.dir/'
as -v --64 -o CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccmm6pzq.s as -v --64 -o CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o /tmp/cch7GwnZ.s
GNU assembler version 2.46.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.46.0 GNU assembler version 2.46.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.46.0
COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/ LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.' COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.'
[2/2] : && /usr/bin/g++ -v -Wl,-v CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_aae80 && : [2/2] : && /usr/bin/c++ -v -Wl,-v CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_a8847 && :
Using built-in specs. Using built-in specs.
COLLECT_GCC=/usr/bin/g++ COLLECT_GCC=/usr/bin/c++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper
Target: x86_64-pc-linux-gnu Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust,cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust,cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes
@ -951,12 +1275,12 @@ events:
gcc version 16.1.1 20260430 (GCC) gcc version 16.1.1 20260430 (GCC)
COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/ LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_aae80' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_aae80.' COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_a8847' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_a8847.'
/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce8QsNN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_aae80 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce2Bg9n.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_a8847 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o
collect2 version 16.1.1 20260430 collect2 version 16.1.1 20260430
/usr/bin/ld -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce8QsNN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_aae80 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o /usr/bin/ld -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce2Bg9n.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_a8847 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o
GNU ld (GNU Binutils) 2.46.0 GNU ld (GNU Binutils) 2.46.0
COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_aae80' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_aae80.' COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_a8847' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_a8847.'
exitCode: 0 exitCode: 0
- -
@ -995,19 +1319,19 @@ events:
Parsed CXX implicit link information: Parsed CXX implicit link information:
link line regex: [^( *|.*[/\\])(ld[0-9]*(|\\.[a-rt-z][a-z]*|\\.s[a-np-z][a-z]*|\\.so[a-z]+)|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] link line regex: [^( *|.*[/\\])(ld[0-9]*(|\\.[a-rt-z][a-z]*|\\.s[a-np-z][a-z]*|\\.so[a-z]+)|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)]
linker tool regex: [^[ ]*(->|"|[0-9]+>[ -]*Build:[ 0-9]+ ms[ ]*)?[ ]*(([^"]*[/\\])?(ld[0-9]*(|\\.[a-rt-z][a-z]*|\\.s[a-np-z][a-z]*|\\.so[a-z]+)))("|,| |$)] linker tool regex: [^[ ]*(->|"|[0-9]+>[ -]*Build:[ 0-9]+ ms[ ]*)?[ ]*(([^"]*[/\\])?(ld[0-9]*(|\\.[a-rt-z][a-z]*|\\.s[a-np-z][a-z]*|\\.so[a-z]+)))("|,| |$)]
ignore line: [Change Dir: '/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-KRXVj0'] ignore line: [Change Dir: '/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-bNmRFu']
ignore line: [] ignore line: []
ignore line: [Run Build Command(s): /usr/bin/ninja -v cmTC_aae80] ignore line: [Run Build Command(s): /usr/bin/ninja -v cmTC_a8847]
ignore line: [[1/2] /usr/bin/g++ -v -o CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp] ignore line: [[1/2] /usr/bin/c++ -v -o CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp]
ignore line: [Using built-in specs.] ignore line: [Using built-in specs.]
ignore line: [COLLECT_GCC=/usr/bin/g++] ignore line: [COLLECT_GCC=/usr/bin/c++]
ignore line: [Target: x86_64-pc-linux-gnu] ignore line: [Target: x86_64-pc-linux-gnu]
ignore line: [Configured with: /build/gcc/src/gcc/configure --enable-languages=ada c c++ d fortran go lto m2 objc obj-c++ rust cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes] ignore line: [Configured with: /build/gcc/src/gcc/configure --enable-languages=ada c c++ d fortran go lto m2 objc obj-c++ rust cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes]
ignore line: [Thread model: posix] ignore line: [Thread model: posix]
ignore line: [Supported LTO compression algorithms: zlib zstd] ignore line: [Supported LTO compression algorithms: zlib zstd]
ignore line: [gcc version 16.1.1 20260430 (GCC) ] ignore line: [gcc version 16.1.1 20260430 (GCC) ]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_aae80.dir/'] ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a8847.dir/']
ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_aae80.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/ccmm6pzq.s] ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_a8847.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/cch7GwnZ.s]
ignore line: [GNU C++20 (GCC) version 16.1.1 20260430 (x86_64-pc-linux-gnu)] ignore line: [GNU C++20 (GCC) version 16.1.1 20260430 (x86_64-pc-linux-gnu)]
ignore line: [ compiled by GNU C version 16.1.1 20260430 GMP version 6.3.0 MPFR version 4.2.2 MPC version 1.4.1 isl version isl-0.27-GMP] ignore line: [ compiled by GNU C version 16.1.1 20260430 GMP version 6.3.0 MPFR version 4.2.2 MPC version 1.4.1 isl version isl-0.27-GMP]
ignore line: [] ignore line: []
@ -1024,15 +1348,15 @@ events:
ignore line: [ /usr/include] ignore line: [ /usr/include]
ignore line: [End of search list.] ignore line: [End of search list.]
ignore line: [Compiler executable checksum: d47d0c990a24bc0dbaf3bd00656bd5f3] ignore line: [Compiler executable checksum: d47d0c990a24bc0dbaf3bd00656bd5f3]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_aae80.dir/'] ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a8847.dir/']
ignore line: [ as -v --64 -o CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccmm6pzq.s] ignore line: [ as -v --64 -o CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o /tmp/cch7GwnZ.s]
ignore line: [GNU assembler version 2.46.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.46.0] ignore line: [GNU assembler version 2.46.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.46.0]
ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/]
ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/] ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.'] ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.']
ignore line: [[2/2] : && /usr/bin/g++ -v -Wl -v CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_aae80 && :] ignore line: [[2/2] : && /usr/bin/c++ -v -Wl -v CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_a8847 && :]
ignore line: [Using built-in specs.] ignore line: [Using built-in specs.]
ignore line: [COLLECT_GCC=/usr/bin/g++] ignore line: [COLLECT_GCC=/usr/bin/c++]
ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper] ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper]
ignore line: [Target: x86_64-pc-linux-gnu] ignore line: [Target: x86_64-pc-linux-gnu]
ignore line: [Configured with: /build/gcc/src/gcc/configure --enable-languages=ada c c++ d fortran go lto m2 objc obj-c++ rust cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes] ignore line: [Configured with: /build/gcc/src/gcc/configure --enable-languages=ada c c++ d fortran go lto m2 objc obj-c++ rust cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes]
@ -1041,13 +1365,13 @@ events:
ignore line: [gcc version 16.1.1 20260430 (GCC) ] ignore line: [gcc version 16.1.1 20260430 (GCC) ]
ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/]
ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/] ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_aae80' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_aae80.'] ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_a8847' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_a8847.']
link line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce8QsNN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_aae80 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] link line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce2Bg9n.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_a8847 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o]
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2] ==> ignore arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2] ==> ignore
arg [-plugin] ==> ignore arg [-plugin] ==> ignore
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so] ==> ignore arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so] ==> ignore
arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper] ==> ignore arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper] ==> ignore
arg [-plugin-opt=-fresolution=/tmp/cce8QsNN.res] ==> ignore arg [-plugin-opt=-fresolution=/tmp/cce2Bg9n.res] ==> ignore
arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
arg [-plugin-opt=-pass-through=-lgcc] ==> ignore arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
arg [-plugin-opt=-pass-through=-latomic_asneeded] ==> ignore arg [-plugin-opt=-pass-through=-latomic_asneeded] ==> ignore
@ -1063,7 +1387,7 @@ events:
arg [/lib64/ld-linux-x86-64.so.2] ==> ignore arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
arg [-pie] ==> ignore arg [-pie] ==> ignore
arg [-o] ==> ignore arg [-o] ==> ignore
arg [cmTC_aae80] ==> ignore arg [cmTC_a8847] ==> ignore
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o]
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o]
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o] arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o]
@ -1075,7 +1399,7 @@ events:
arg [-L/lib] ==> dir [/lib] arg [-L/lib] ==> dir [/lib]
arg [-L/usr/lib] ==> dir [/usr/lib] arg [-L/usr/lib] ==> dir [/usr/lib]
arg [-v] ==> ignore arg [-v] ==> ignore
arg [CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore arg [CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
arg [-lstdc++] ==> lib [stdc++] arg [-lstdc++] ==> lib [stdc++]
arg [-lm] ==> lib [m] arg [-lm] ==> lib [m]
arg [-lgcc_s] ==> lib [gcc_s] arg [-lgcc_s] ==> lib [gcc_s]
@ -1087,7 +1411,7 @@ events:
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o] arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o]
arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o]
ignore line: [collect2 version 16.1.1 20260430] ignore line: [collect2 version 16.1.1 20260430]
ignore line: [/usr/bin/ld -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce8QsNN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_aae80 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_aae80.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] ignore line: [/usr/bin/ld -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cce2Bg9n.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_a8847 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_a8847.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o]
linker tool for 'CXX': /usr/bin/ld linker tool for 'CXX': /usr/bin/ld
collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] ==> [/usr/lib/Scrt1.o] collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] ==> [/usr/lib/Scrt1.o]
collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] ==> [/usr/lib/crti.o] collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] ==> [/usr/lib/crti.o]

View File

@ -1,3 +1,4 @@
/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/saqut.dir /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/saqut.dir
/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/test.dir
/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/edit_cache.dir /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/edit_cache.dir
/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/rebuild_cache.dir /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/rebuild_cache.dir

View File

@ -0,0 +1,46 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by CMake Version 4.3
# ALL_GOLDEN_SQT at CMakeLists.txt:40 (file)
file(GLOB_RECURSE NEW_GLOB LIST_DIRECTORIES false "/home/saqut/Masaüstü/saqutcompiler/tests/golden/*.sqt")
set(OLD_GLOB
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/basic.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/compound_mod.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/mod_by_zero.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/precedence.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/fibonacci/fib.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/logic/not_operator.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/logic/short_circuit.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/basic.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/do_while_once.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/do_while_truthy.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/for_break_continue.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/nested_break.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/while_break_continue.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/dce.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/folding.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/run_opt.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/equality.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/hello.sqt"
"/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/ordering_error.sqt"
)
if(NOT "${NEW_GLOB}" STREQUAL "${OLD_GLOB}")
message("-- GLOB mismatch!")
set(NEW_ONLY ${NEW_GLOB})
set(OLD_ONLY ${OLD_GLOB})
list(REMOVE_ITEM NEW_ONLY ${OLD_GLOB})
list(REMOVE_ITEM OLD_ONLY ${NEW_GLOB})
if(NEW_ONLY)
message("The following files were added:")
foreach(VAR_FILE IN LISTS NEW_ONLY)
message(" +${VAR_FILE}")
endforeach()
endif()
if(OLD_ONLY)
message("The following files were removed:")
foreach(VAR_FILE IN LISTS OLD_ONLY)
message(" -${VAR_FILE}")
endforeach()
endif()
file(TOUCH_NOCREATE "/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/cmake.verify_globs")
endif()

View File

@ -0,0 +1 @@
# This file is generated by CMake for checking of the VerifyGlobs.cmake file

View File

@ -79,6 +79,15 @@ rule RERUN_CMAKE
generator = 1 generator = 1
#############################################
# Rule for re-checking globbed directories.
rule VERIFY_GLOBS
command = /usr/bin/cmake -P /home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/VerifyGlobs.cmake
description = Re-checking globbed directories...
generator = 1
############################################# #############################################
# Rule for cleaning all built files. # Rule for cleaning all built files.

48
build/CTestTestfile.cmake Normal file
View File

@ -0,0 +1,48 @@
# CMake generated Testfile for
# Source directory: /home/saqut/Masaüstü/saqutcompiler
# Build directory: /home/saqut/Masaüstü/saqutcompiler/build
#
# This file includes the relevant testing commands required for
# testing this directory and lists subdirectories to be tested as well.
add_test(unit_tests "bash" "/home/saqut/Masaüstü/saqutcompiler/tests/run.sh")
set_tests_properties(unit_tests PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;31;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_arithmetic_basic "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/basic.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/basic.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_arithmetic_basic PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_arithmetic_compound_mod "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/compound_mod.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/compound_mod.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_arithmetic_compound_mod PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_arithmetic_mod_by_zero_runtime_error "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/mod_by_zero.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/mod_by_zero.runtime_error" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden_error.cmake")
set_tests_properties(golden_arithmetic_mod_by_zero_runtime_error PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;109;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_arithmetic_precedence "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/precedence.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/arithmetic/precedence.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_arithmetic_precedence PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_fibonacci_fib "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/fibonacci/fib.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/fibonacci/fib.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_fibonacci_fib PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_logic_not_operator "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/logic/not_operator.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/logic/not_operator.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_logic_not_operator PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_logic_short_circuit "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/logic/short_circuit.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/logic/short_circuit.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_logic_short_circuit PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_loops_basic "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/basic.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/basic.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_loops_basic PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_loops_do_while_once "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/do_while_once.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/do_while_once.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_loops_do_while_once PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_loops_do_while_truthy "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/do_while_truthy.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/do_while_truthy.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_loops_do_while_truthy PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_loops_for_break_continue "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/for_break_continue.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/for_break_continue.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_loops_for_break_continue PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_loops_nested_break "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/nested_break.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/nested_break.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_loops_nested_break PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_loops_while_break_continue "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/while_break_continue.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/loops/while_break_continue.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_loops_while_break_continue PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_opt_dce_ir_opt "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/dce.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/dce.ir_opt.expected" "-DCOMMAND=ir" "-DOPTIMIZED=1" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_opt_dce_ir_opt PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;64;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_opt_folding_ir_opt "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/folding.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/folding.ir_opt.expected" "-DCOMMAND=ir" "-DOPTIMIZED=1" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_opt_folding_ir_opt PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;64;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_opt_run_opt "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/run_opt.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/run_opt.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_opt_run_opt PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_opt_run_opt_run_opt "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/run_opt.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/opt/run_opt.run_opt.expected" "-DOPTIMIZED=1" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_opt_run_opt_run_opt PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;80;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_string_equality "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/equality.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/equality.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_string_equality PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_string_hello "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/hello.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/hello.expected" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden.cmake")
set_tests_properties(golden_string_hello PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;51;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")
add_test(golden_string_ordering_error_compile_error "/usr/bin/cmake" "-DBINARY=/home/saqut/Masaüstü/saqutcompiler/build/saqut" "-DSOURCE=/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/ordering_error.sqt" "-DEXPECTED=/home/saqut/Masaüstü/saqutcompiler/tests/golden/string/ordering_error.compile_error" "-P" "/home/saqut/Masaüstü/saqutcompiler/cmake/run_golden_error.cmake")
set_tests_properties(golden_string_ordering_error_compile_error PROPERTIES _BACKTRACE_TRIPLES "/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;95;add_test;/home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt;0;")

File diff suppressed because one or more lines are too long

39
cmake/run_golden.cmake Normal file
View File

@ -0,0 +1,39 @@
# run_golden.cmake tek bir golden test çalıştırır ve çıktıyı karşılaştırır.
#
# Parametreler (cmake -D ile geçilir):
# BINARY saqut binary yolu
# SOURCE test .sqt dosyası (tam yol)
# EXPECTED beklenen çıktı dosyası (tam yol)
# COMMAND "run" (varsayılan) veya "ir"
# OPTIMIZED 1 ise --optimized bayrağı eklenir
if(NOT DEFINED COMMAND)
set(COMMAND "run")
endif()
set(EXTRA_FLAGS "")
if(OPTIMIZED)
list(APPEND EXTRA_FLAGS "--optimized")
endif()
execute_process(
COMMAND "${BINARY}" "${COMMAND}" ${EXTRA_FLAGS} "file:${SOURCE}"
OUTPUT_VARIABLE ACTUAL
ERROR_VARIABLE STDERR_OUT
RESULT_VARIABLE EXIT_CODE
)
if(NOT EXIT_CODE EQUAL 0)
message(FATAL_ERROR
"saqut ${COMMAND} başarısız (exit ${EXIT_CODE}):\n${STDERR_OUT}")
endif()
file(READ "${EXPECTED}" EXPECTED_CONTENT)
if(NOT ACTUAL STREQUAL EXPECTED_CONTENT)
message(FATAL_ERROR
"Çıktı uyuşmuyor: ${SOURCE}\n"
"--- BEKLENEN ---\n${EXPECTED_CONTENT}"
"--- GERÇEK ---\n${ACTUAL}"
)
endif()

View File

@ -0,0 +1,29 @@
# run_golden_error.cmake derleme hatası BEKLEYEN golden test.
#
# Parametreler (cmake -D ile geçilir):
# BINARY saqut binary yolu
# SOURCE test .sqt dosyası (tam yol)
# EXPECTED beklenen hata içeriği (.compile_error dosyası); stderr bu
# metni içermeli (regex veya düz dize olarak eşleşir)
execute_process(
COMMAND "${BINARY}" run "file:${SOURCE}"
OUTPUT_VARIABLE STDOUT_OUT
ERROR_VARIABLE STDERR_OUT
RESULT_VARIABLE EXIT_CODE
)
if(EXIT_CODE EQUAL 0)
message(FATAL_ERROR
"Derleme hatası bekleniyordu ama program başarıyla çalıştı: ${SOURCE}\n"
"Çıktı: ${STDOUT_OUT}")
endif()
file(READ "${EXPECTED}" EXPECTED_CONTENT)
string(STRIP "${EXPECTED_CONTENT}" EXPECTED_CONTENT)
if(NOT STDERR_OUT MATCHES "${EXPECTED_CONTENT}")
message(FATAL_ERROR
"Beklenen '${EXPECTED_CONTENT}' mesajı stderr'de bulunamadı: ${SOURCE}\n"
"Stderr: ${STDERR_OUT}")
endif()

View File

@ -10,12 +10,11 @@
> 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**; > ✅ **Uygulama durumu:** Bu belgedeki ADR-006…019 kararlarında tarif edilen
> tarif edilen makine (sembol tablosu, semantik analiz, tip sistemi, diagnostic, > makine **kodlandı ve çalışıyor.** Sembol tablosu, semantik analiz, tip sistemi,
> optimizasyon, IR+VM) **henüz kodlanmamıştır.** Bugün çalışan: lexer, tokenizer, > diagnostic motoru, optimizasyon (constant folding + DCE), IR üreteci ve bytecode
> Pratt parser, AST, AST'nin JSON serileştirmesi, CLI iskeleti, konum takibi ve > VM'in tamamı uygulandı. `examples/fibonacci.sqt` uçtan uca çalışıyor.
> basit aritmetiği düşüren minimal bir IR deneyi. Hiçbir ADR, var olmayan bir > Güncel "çalışıyor / henüz yok" listesi için bkz. `CLAUDE.md`.
> mekanizmayı varmış gibi anlatmaz.
--- ---
@ -105,46 +104,45 @@ sembol tablosunun optimizasyondan önceki ve sonraki halini ayrı ayrı görebil
symbol bağı, erişilebilirlik, constness ekler). Ağacı **bozmaz**, zenginleştirir. symbol bağı, erişilebilirlik, constness ekler). Ağacı **bozmaz**, zenginleştirir.
Orijinal AST hâlâ kaynak kodun tam izdüşümüdür. Orijinal AST hâlâ kaynak kodun tam izdüşümüdür.
2. **Optimizasyon dönüşümü, ağacın bir KOPYASI (klon) üzerinde yapılır.** 2. **Optimizasyon dönüşümü iki yolla yapılabilir:**
Orijinal analizli AST = "öncesi"; klon + dönüştürülmüş AST = "sonrası".
Ağaç klonlamak ucuz ve basittir, yalnızca `--optimized` istendiğinde yapılır.
**Sonuç:** Hem "bellek canavarı" felsefesi korunur (orijinal AST her şeyi tutar), a. **`ast` komutu için klon:** orijinal AST dokunulmadan kalır, klon üstünde
hem optimizasyon yapılır, hem de öncesi/sonrası ayrı ayrı incelenebilir. pass'ler çalışır. Kullanıcı "öncesi" ve "sonrası" AST'yi ayrı ayrı
görebilir. `OptimizationManager::optimize()` bu yolu kullanır.
b. **Diğer tüm komutlar için yerinde (in-place):** `run --optimized`,
`ir --optimized` vb. tek versiyon üretiyor — orijinali saklamaya gerek yok.
`OptimizationManager::runPassesInPlace()` bu yolu kullanır, klon maliyeti yok.
**Sonuç:** "bellek canavarı" felsefesi `ast` komutunda korunur; diğer komutlar
gereksiz klon maliyeti taşımaz.
``` ```
saqut ast file.sqt → ham + annotate edilmiş AST (1+2 burada durur) saqut ast file.sqt → ham + annotate edilmiş AST (1+2 burada durur)
saqut ast file.sqt --optimized → klon, folding uygulanmış (3 var) saqut ast file.sqt --optimized → klon, folding uygulanmış (3 var)
saqut run file.sqt --optimized → yerinde optimize → IR → VM (klon yok)
saqut ir file.sqt --optimized → yerinde optimize → IR dump (klon yok)
``` ```
### Güncelleme — Klon maliyeti yük taşır (load-bearing) ### Güncelleme — Klon ve sembol tablosu paylaşımı
İlk metin "ağaç klonlamak ucuz ve basittir" diyordu; bu **klon maliyetini hafife `deepClone` sembol tablosunu yeniden eşlemez (remap etmez) — klondaki
alıyor** ve bir **tutarlılık (coherence) problemini** atlıyordu. Düzeltme: `IdentifierNode::resolvedSymbol` orijinal `Symbol` nesnelerini gösterir. Bu
**güvenlidir**, çünkü:
`ASTNode::clone()` "belki gerekir" değil, **merkezi ve spesifiye edilmesi - `Symbol::references` bir **konum listesi** (`std::vector<SourceLocation>`),
zorunlu** bir bileşendir; tüm öncesi/sonrası hikâyesi ona dayanır (bkz. roadmap referans sayacı değildir. Klonda bir `IdentifierNode` silindiğinde bu liste
Faz 4'te clone() yükseltildi). değişmez.
- `IdentifierNode` destructor'ı yoktur; `resolvedSymbol`'e dokunan hiçbir yıkıcı
kodu çalışmaz.
- Klondaki pass'ler Symbol nesnelerini **okur** (slot numarası, tip vb.),
**yazmaz** — paylaşım salt-okunur (read-only) kullanımdır.
**Klonlanırken karar verilmesi gereken iki nokta (açıkça belgele):** **Parent pointer'lar** ise yeniden bağlanır — klon node'larının `parent`'ı
orijinali değil, klonu gösterir (deepClone bunu zaten yapar).
1. **Parent pointer'lar yeniden bağlanmalı.** Klon node'larının `parent`'ı Önceki versiyon "sembol tablosu klonlanır ve remap edilir" diyordu; bu hem hiç
orijinali değil, klonu göstermeli; yoksa yapısal doğrulama ve dönüşümler implement edilmedi hem de gerekli değildi. Düzeltildi.
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.
--- ---
@ -513,6 +511,11 @@ bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır:
### Güncelleme — Scope-tabanlı bellek artık GEREKÇELİ (bağımlılığı belgele) ### Güncelleme — Scope-tabanlı bellek artık GEREKÇELİ (bağımlılığı belgele)
> ⚠️ **İPTAL — bu güncelleme ADR-020 ile geçersiz kılındı.** Bileşik tipler artık
> runtime'da referans (JS/Java/C# modeli); bileşikler scope'tan kaçar, bellek
> erişilebilirliğe bağlı, geri-kazanım stratejisi (#56) gerekecek. Aşağıdaki
> "GC gerekmez" sonucu **artık geçerli değildir** — tarihsel bağlam için bırakıldı.
Önceki kaygı ("scope çıkışında free, aliasing/escape altında bozulur") kilitli Önceki kaygı ("scope çıkışında free, aliasing/escape altında bozulur") kilitli
dil kimliğiyle **lehte çözüldü:** dil kimliğiyle **lehte çözüldü:**
@ -662,12 +665,457 @@ modelini birlikte zorlar — ikisi de bu yüzden ertelendi.
--- ---
## ADR-020: Değer vs Referans Semantiği — Bileşik Tipler Runtime'da Referanstır
### Bağlam
ADR-014/018/019 boyunca bellek modeli tek bir **taşıyıcı varsayıma** dayanıyordu:
> "kullanıcı pointer'ı yok + kaçan referans yok → array/struct scope'tan kaçamaz
> → scope-tabanlı bellek çalışır, **GC gerekmez**."
Bu varsayım, `interface`'in (ADR-018) ve closure'ın ertelenmesinin de ikinci
gerekçesiydi. Tasarım oturumunda **bilinçli olarak değiştirildi.** "Pointer yok"
ilkesinin gerçekte ne demek olduğu netleşti:
> **"Pointer/referans yok" = kullanıcıya `&`/`*` *sözdizimi* verilmez.**
> Bu bir *value-semantics* iddiası değildi; amacı sözdizimsel pointer kontrolünü
> kullanıcıdan almaktı. Derleyici ve runtime, bileşik değerleri her aşamada
> **referansla** taşır — aksi halde her atama/çağrı/dönüşte derin kopya yaşanır
> ve bağlı yapılar (node) imkânsızlaşırdı.
### Karar
✅ **İki katmanlı semantik (JavaScript / Java / C# nesne modeli):**
| Kategori | Tipler | Atama / parametre semantiği |
|---|---|---|
| **Primitive** | `int`, `float`, `bool`, (`char` vb.) | **Saf değer** — kopyalanır |
| **Bileşik (referans)** | `struct`, `array`, `string`\*, (ileride `class`, `function`) | **Referans** — paylaşılır |
- `a=0; b=a; b=5``a` hâlâ `0` (primitive kopya). Fonksiyon parametresinde de aynı.
- `func(arr)` → array'in **kendisi** geçer; `func` içinde değişen çağıranı **etkiler**.
- `func(arr[0])` → eleman primitive → **kopya**; çağıranı **etkilemez**.
- \* `string`'in primitive-gibi mi (immutable değer) yoksa referans mı sayılacağı
ayrı bir alt-karar; #40 ile beraber netleşecek.
**`class` ve `function` tipleri sözdizimsel olarak rezerve** — şu an semantik
yok, backend'i ilgilendirmez; ileride referans tip olarak gelecekler. Lexer/parser
keyword'leri tanıyıp "henüz desteklenmiyor" diyebilir. (ADR-014'teki "class yok
sayılır" maddesi bu yönde yumuşatıldı: yok sayılmaz, rezerve edilir.)
### Bilinçli geri açtığımız problem: kaçma / yaşam-süresi
Bu karar, ADR-014'ün "scope-tabanlı bellek GEREKÇELİ / GC gerekmez" sonucunu
**iptal eder.** Referansla:
1. **Aliasing gerçek.** `b = a; b.x = 5``a.x` de değişir. "Takma ad yok, akıl
yürütmesi kolay" sadeliği takas edildi. **Determinizm korunur** — tek
iş-parçacığı, deterministik kayıt-tekrar / time-travel debug hâlâ doğal; takas
edilen yalnızca aliasing-özgürlüğüdür.
2. **Bileşikler scope'tan kaçar.** Bir node `return` edilebilir veya başka bir
struct'ın alanında saklanabilir → "scope çıkışında free" **artık yanlış.**
Sahiplik scope'a değil **erişilebilirliğe** bağlı.
3. **Döngüsel yapılar artık meşru ve istenen.** `struct Node { Node next; }`
ADR-011/014'te `E010` ile yasaktı (by-value → sonsuz boyut). Referansla alan
pointer-boyutlu → **sonlu** → bağlı liste / ağaç / graf **yazılabilir.** Bunlar
dilin hedef kullanımının kalbi: XML node'ları, JSON kalıpları, class'sız ORM.
**Sonuç:** `E010` revize edilmeli — referansla tutulan struct alanı için döngü
artık hata değildir.
### Bunun açtığı zorunlu problem (ayrı issue)
Döngüsel referans → naif **referans sayımı (`shared_ptr`) sızdırır.** Bu artık
"olabilir" değil, dilin **hedeflediği** yapıların (graf/döngü) doğrudan sonucu.
Bir geri-kazanım stratejisi (izleyici GC / döngü toplayıcı) **kesinlikle**
gerekecek. Bu güçlü mimari borç **#56**'da izlenir ve `karar-gerekli`. v1 motoru
`shared_ptr` ile başlayıp döngüyü **bilinçli ve belgeleyerek** sızdırabilir, ama
ürünleşmeden önce çözülmek zorundadır.
### İptal/revize edilen önceki kararlar
- **ADR-014** — "scope-tabanlı bellek GEREKÇELİ / GC gerekmez" sonucu **iptal.**
Bellek artık scope'a değil erişilebilirliğe bağlı; geri-kazanım stratejisi #56.
- **ADR-018 / ADR-019**`interface` / closure'ı ertelemenin "kaçma problemini
yeniden açar" gerekçesi **artık geçersiz** (problem zaten açık). Bu ikisini
*daha kolay* alınabilir kılar — ama hâlâ kapsam dışı, sadece engeli değişti.
- **ADR-011**`E010` döngüsel struct kuralı revize edilecek (yukarı bkz.).
---
## ADR-021: Null Güvenliği — `Type?` Nullable + Akış-Duyarlı Null Analizi
### Bağlam
ADR-020 ile bileşik tipler referans oldu. Referans, "gösterecek bir şey yok"
durumunu (bağlı listenin sonu, başlatılmamış alan) **zorunlu** kılar. "null her
yerde" (Java/C#/JS) milyar dolarlık hatadır: null-deref çalışma zamanında patlar.
saQut'un kimliği "kafes — derleyici/VM seni korur" → bunu derleme zamanında
yakalamak istiyoruz.
### Karar
✅ **Kotlin/Swift modeli: varsayılan null-OLAMAZ, nullable açıkça `?` ile.**
- `Node a` → asla null olamaz; başlatılması zorunlu.
- `Node? a` → null olabilir; başlatılmazsa değeri **`null`**.
- `null` literali yalnızca `T?` tipine atanabilir; `Node a = null`**derleme hatası**.
- `T?` üstünde doğrudan alan/eleman erişimi (`a.next`) → **derleme hatası**
(önce null-kontrolü şart).
### Atama/operand kuralı`T <: T?` (tek yönlü), katı
**Alt-tip:** `T <: T?`. Yani:
- `int? a = 5;` → ✓ (int → int?, **genişletme serbest**).
- `int a = bir_int?;` → ✗ (int? → int, **daraltma yasak**).
**Katı operand kuralı:** non-null bir bağlamda — atamanın sol tarafı, **her
operatör operandı**, non-null bekleyen bir argüman — değer **statik olarak non-null**
olmalı. `int a = b + c + d`'de `b/c/d`'den **biri bile** nullable ise → **derleme
hatası.** Sembol tablosu/akış görünümü seviyesinde: `notnull = notnull + notnull + …`.
Sezgi yok, deterministik. (`notnull + notnull` → `notnull`.)
### Akış-duyarlı null analizi (flow-sensitive narrowing)
`T?` bir değişken **program noktasına göre** "kesin non-null" kanıtlandıysa
daraltılır:
```c
Node? a = ...;
// a.next; // E0xx: a null olabilir
if (a != null) {
a.next; // OK — bu dalda a, Node'a daraltıldı
}
// a.next; // yine hata (daldan çıkıldı)
if (a == null) return; // guard / erken çıkış
a.next; // OK — buradan sonrası kesin non-null
```
`if` bu sistemin **bel kemiğidir** — sadece büyük/küçük/eşitlik değil, nullable
aklamanın da aracı. **İki form da desteklenir:**
1. **Nested (blok-kapsamlı):** `if (a != null) { /* a: T burada */ }`. Ayrıca
`if/else`'in zıt dalı, `while (a != null) { … }`.
2. **Sıralı (guard / erken-çıkış):** `if (a == null) return; /* a: T bundan sonra */`.
Dal kesin çıkıyorsa (`return`/`throw`/`break`/`continue`) negasyonu **ardışık**
koda taşınır.
**Mekanik:** CFG üzerinde ileri-yönlü dataflow; her nullable değişken için kafes
`{MaybeNull, NonNull}`. Koşullarda daraltma (`!= null`, `== null` guard, `&&`
kısa-devre sağ tarafı); kesin-çıkış dalları negasyonu ardına taşır; birleşme (join)
muhafazakâr (bir daldan MaybeNull gelirse MaybeNull); atama RHS'e göre sıfırlar.
> **Karmaşıklaştırma sınırı:** narrowing yalnızca **doğrudan test edilen değişken**
> için tanınır (`x == null`/`x != null`). **Alias takibi YOK** (`y = x; if (y != null)`
> → x daralmaz) ve keyfi teorem-ispatı yok. Bu, derleyiciyi basit tutarken yaygın
> durumların hepsini kapsar → developer **uzun/karmaşık kod yazmak zorunda kalmaz.**
> **Runtime maliyeti SIFIR** — tamamen derleme-zamanı analizi; üretilen kodda
> fazladan kontrol yok.
### Kaçış kapısı YOK — `!` ve `??` YASAK
Null **yalnızca görünür kontrol akışıyla** (yukarıdaki `if` narrowing) aklanır.
Gizli runtime null-aklama operatörleri **yasaktır:**
- ❌ **`x!`** (non-null iddiası) — "compiler'a güvenme, runtime'da kontrol et"
= statik garantiyi delen gizli backdoor. *(ADR-021'in ilk taslağındaki `a!`
KALDIRILDI.)*
- ❌ **`x ?? default`** (elvis), **`x?.field`** (güvenli çağrı) — null durumunu
sessizce gizleyen şeker.
> Ayrım: `as int`'in başarısızlıkta fırlatması yasak **değil** — o bir null-backdoor
> değil, kendiliğinden başarısız olabilen bir *dönüşüm* (ADR-026).
### Frontend her şeyi kesin çözer (backend-bağımsızlık)
Nullability **tamamen frontend'de** çözülür; tüm null-güvenlik hataları IR'den
**önce** verilir. Backend'ler (IR+VM, ileride C-transpile) null-güvenliği **yeniden
analiz etmez** — garantiyi hazır devralır (ADR-006/019). Bu sayede: well-typed saf
saQut kodu **statik null-güvenlidir** → non-null referans deref'i runtime null-kontrolü
**gerektirmez** (perf + sadelik). Runtime null-deref hatası (ADR-025) bu yüzden
geriye esas olarak **FFI sınırı** (host non-null sözünü çiğnerse) ve savunma amaçlı
backstop olarak kalır — saf saQut kodu bunu üretmez.
### Mimari yeri
Bu, saQut'un ilk gerçek **akış-duyarlı** analizidir. **Yapısal kontrol akışı**
üstünde (AST + structured CFG) yapılabilir; tam SSA gerektirmez → **#2 (CFG/SSA
gerekli mi?)** için somut veri: şimdilik yapısal akış analizi yeter. **#20**
(akıllı diagnostic) bu analizden beslenir ("burada null olabilir, çünkü …").
---
## ADR-022: Bellek Geri-Kazanımı — Basit Deterministik Mark-Sweep + GC-Hazır Nesne Modeli
### Bağlam
ADR-020 referans semantiği → döngüsel yapılar (#56). Kısıtlar: GC **basit ve
deterministik** olmalı, "karmaşık ve rastgele" istenmiyor. Ayrıca bu, **geç
değiştirilmesi en pahalı** karardır (nesne modeline işler) → topuğa sıkmamak
kritik.
### Önce yanlış-eşleştirmeyi temizle
**`null`/`?` GC'yi zorlaştırmaz.** Nullable tamamen derleme-zamanı/tip meselesidir;
runtime'da null referans sadece "boş işaretçi" → GC için *daha kolay* (izlenecek
nesne yok). null ile GC **dik (orthogonal)**; aralarında gerilim yoktur.
### Seçenekler ve neden mark-sweep
| Strateji | Döngü | Basitlik | Topuğa-sıkma riski |
|---|---|---|---|
| Refcount (`shared_ptr` her yerde) | ❌ sızdırır | başta basit | **Yüksek** — node dilinde döngü kaçınılmaz; üstüne döngü toplayıcı = CPython karmaşıklığı (tam "karmaşık/rastgele") |
| **Mark-sweep, taşımasız, stop-the-world** | ✅ | **en basit *doğru* GC** | **Düşük** — gelişmiş GC'lerin tabanı; üstüne eklenir, yeniden yazılmaz |
| Generational / incremental / compacting | ✅ | karmaşık (write barrier, remembered set) | pause'lar belirsizleşir = istenmeyen "rastgele" |
✅ **Karar: taşımasız (non-moving), stop-the-world, basit mark-sweep.**
- Döngüleri **bedavaya** toplar (izleme döngü umursamaz) → #56'yı gerçekten çözer.
- **Deterministik:** GC belirli safepoint'lerde çalışır (ör. her N tahsiste) →
kayıt-tekrar / time-travel bit-aynı kalır ("cage" korunur). "Rastgele" değil.
- Taşımasız → işaretçi düzeltme / barrier yok → VM'in geri kalanı GC'ye katılmak
zorunda değil. *Crafting Interpreters*'ın `clox`'u tam bunu yapar (~birkaç yüz satır).
### Topuğa-sıkmama kuralı — nesne modelini ŞİMDİ GC-hazır kur
Asıl risk GC'yi *yazmak* değil, nesne modelini sonradan ona uyduramamaktır. O
yüzden **bugünden** (toplama yokken bile):
1. Her heap nesnesine küçük **header**: tip tag + mark biti + tüm-nesneler listesi için `next`.
2. VM **kök (root) sayımı** yapabilsin: operand stack, frame local'leri, global'ler.
3. Bir nesne **içerdiği referansları** sayabilsin: referans-tipli struct alanları,
referans-tipli array elemanları.
Bu üçü hazırsa "mark-sweep'i aç" **lokal bir ekleme** olur, nesne-modeli yeniden
yazımı değil.
### Aşamalandırma (#56'nın yönü)
- **v1 (şimdi):** GC-header'lı tahsis + intrusive tüm-nesneler listesi + kök sayımı.
**Toplama yok** (program sonunda hepsini bırak / arena). Fibonacci/test ölçeğinde
sorunsuz; kısa programlar sızıntıdan etkilenmez.
- **v2 (#56 ciddileşince):** aynı header+kök+çocuk-sayımı üstünde mark-sweep'i aç.
Model yeniden yazılmaz.
- **`shared_ptr`'dan kaçın:** v1'de bile her referansa refcount gömmek, sonra
mark-sweep için **sökmek** ayrı bir topuğa-sıkmadır. Baştan GC-header modeli kur,
sadece henüz toplama.
### Performans notu — asıl "katil" nerede?
- **Nullability / null:** runtime maliyeti **sıfır** — katil değil.
- **Referans modeli:** her bileşik heap'te + işaretçi dolaylılığı → düzenli ama
yönetilebilir maliyet; ileride **escape analizi** ile kaçmayan nesneleri stack'e
alıp *semantiği bozmadan* hızlandırılır (opt-in, sonra).
- **Tek yüksek-değişim-maliyetli karar = GC.** Onu da (a) basit mark-sweep seçip
(b) modeli baştan GC-hazır kurarak de-risk ettik. **Kaçınılacak gerçek katil:
refcount'u kalıcı model yapmak.**
---
## ADR-023: Eşitlik Semantiği — Referanslarda Kimlik Eşitliği (`==`)
### Bağlam
ADR-020 ile bileşik tipler referans. `==` / `!=` referans tipler için ne yapsın?
Yapısal (derin) eşitlik sezgisel ama üç sorunu var: (1) büyük yapıda **derin
gezinme maliyeti**, (2) yeni açtığımız **döngüsel grafta sonsuz döngü** riski
(ziyaret-takibi şart), (3) seçtiğimiz referans modeliyle **tutarsız**.
### Karar
✅ **Kimlik eşitliği (A):**
| Kategori | `==` davranışı |
|---|---|
| Primitive (`int`/`float`/`bool`) | **değer** karşılaştırması (`3 == 3`) |
| Referans (`struct`, `array`) | **kimlik** — aynı nesne mi? (işaretçi aynılığı) |
| `string` | ⏸️ **#40'a bağlı** — aşağıdaki nota bak |
| `null` | `null == null` → true; `null == nesne` → false; `a == null` null-daraltma deyimi (ADR-021) |
İçerik karşılaştırması istenirse **ayrı, niyeti görünür** bir mekanizmayla gelir
(ileride builtin `deepEquals()` / PHP'nin `==` vs `===` vs `clone` ailesi gibi) —
asla sessizce `==`'e bağlanmaz. Gerekçe: deepEqual'ı `==`'e bağlamak büyük/döngüsel
yapılarda performans ve sonsuz-döngü tuzağıdır; "cam kutu, sürpriz yok" kimliğiyle
de çelişir.
### ⚠️ String istisnası (Java gotcha'sı)
Saf kimlik eşitliğini string'e de uygularsak `"abc" == "abc"`**false** olur —
Java'nın en çok sövülen hatası. Çoğu dil string'i istisna yapar (JS'te string
primitive → içerik; C# overload; Python intern). Bu yüzden **string'in `==`'i
içerik eşitliği olmalı**, ki bu string'i **immutable değer-tipi** olarak modellemeyi
güçlü biçimde öneriyor (bkz. #40). ADR-023 struct/array'i kilitler; string'in `==`'i
#40'ta netleşir ama **varsayılan yön: içerik eşitliği.**
### Açık (ileride, çok uzak — şimdi karar değil)
- **`obj == obj`'i hata/uyarı yapmak:** kullanıcıyı niyetini açık yazmaya zorlamak
(kimlik mi içerik mi). Daha katı bir duruş; v0'da `==` = kimlik serbest.
- **Kullanıcı-tanımlı eşitlik (OOP'siz):** ileride bir tip için `equals(T,T)->bool`
konvansiyonu veya benzeri ile `==`'i kullanıcının tanımlamasına izin vermek —
operator-overload'un OOP'siz karşılığı. Çok uzak.
---
## ADR-024: String — Immutable Değer-Tipi, İç Temsil UTF-8
### Bağlam
ADR-020 string'i "bileşik (referans)" listesine `?` ile koymuştu; ADR-023 string
`==`'inin **içerik** olmasını istedi (Java gotcha'sından kaçınmak için). İkisi de
string'i değişmez-değer modeline itti.
### Karar
✅ **String = immutable (değişmez) değer-tipi; iç temsil UTF-8 bayt.**
- **Immutable:** oluşturulduktan sonra içeriği değişmez; `s = s + "x"` **yeni**
string üretir, eskisini değiştirmez.
- **`==` içerik eşitliği** (ADR-023 istisnası). Paylaşılınca değişmediği için
içerik-eşitliği güvenlidir; aliasing sürprizi yok (JS'in string'i primitive gibi
davranmasının sebebi budur).
- **GC dostu:** serbestçe paylaşılır / intern edilebilir.
- **İç temsil UTF-8** (Rust/Go/Swift hattı): kompakt, web-doğal, ASCII'de ucuz.
`s[i]` **karakter** indeksi O(1) **değildir** → bayt / scalar / grapheme erişimi
**açıkça** ayrılır; sahte O(1) vaat edilmez (Java/JS'in "uzunluk emoji'de yalan
söylüyor" sürprizinden kaçın). Host tarafında `std::string` ham bayt olarak oturur.
- **Verimli birleştirme** için ileride ayrı **builder** tipi (StringBuilder / `join`)
— çekirdeği kirletmeden, döngüde O(n²)'den kaçınmak için.
### Etkilenen
- **#40** (string işlem yüzeyi) bu kararla netleşti; **#9** (iç temsil) = UTF-8.
- ADR-020'deki string `?` işareti → "değer-tipi" olarak çözüldü.
---
## ADR-025: Hata Yönetim Modeli — Struct-Tabanlı Yakalanabilir Hatalar (Swift-tarzı)
### Bağlam
ADR-020 (struct = referans) → null bir struct alanına erişim/yazma ihtimali doğdu:
klasik NullPointerException. ADR-021 statik analizi *kanıtlayabildiğini* derleme
zamanında yakalar, ama `!` iddiası ve kanıtlanamayan durumlar (struct alanı,
cross-fonksiyon) için bir **runtime backstop** gerekir. Ayrıca array OOB, /0 gibi
faults. Java/C#/JS bunları **yakalanabilir** hata yapar — ama OOP exception
hiyerarşisi (`extends Exception`) bizde yok.
### Karar
✅ **Yakalanabilir, struct-tabanlı hata modeli — OOP'siz.**
Hata *değeri* Swift gibi (düz struct, hiyerarşi/extend yok); *görünürlük* Java/C#/JS
gibi (**unchecked** — fonksiyon işaretlenmez, klasik `try{}catch{}`). "Exception'ın
tanıdık catch-and-jump ergonomisi + OOP'suz değer."
1. **Hata değeri = standart built-in struct** — extend yok, OOP yok, deterministik:
```
struct Error {
int line; // hata satırı
int col; // sütun ("char" tip adıyla çakışmaması için col)
string message; // insan-okunur (derleyicinin W/E kataloğundan)
string trace; // stacktrace, en içten dışa
string code; // makine-okunur W/E kodu (E010 vb.) — JSON/toolbox filtresi
}
```
2. **try/catch (unwind + jump):** hata oluşunca en yakın çevreleyen `catch`'e
zıplanır; `catch (e)``e : Error`.
3. **Runtime null-deref = yakalanabilir hata** (NPE analoğu). ADR-021 statik
analizinin **backstop'u**: `a!` patlayınca + analizin kanıtlayamadığı durumlar.
Array OOB ve /0 da aynı kapıdan.
4. **`throw`** ile kullanıcı da hata kaldırabilir (`Error` doldurup).
5. **Determinizm:** unwind deterministik; stacktrace frame'lerden üretilir;
time-travel/replay handle eklenebilir.
### Görünürlük — KARAR: (ii) görünmez / unchecked (Java/C#/JS usulü)
**Fonksiyonlar işaretlenmez.** "Bu hata yapabilir / yapamaz" anotasyonu **YOK**
(C++'ın `noexcept`/`constexpr` benzeri kirlilik istenmiyor). Çağrıda `try f()`
işareti de yok. **Klasik `try { ... } catch (e) { ... }` bloğu** — "anam babam usulü".
**Gerekçe:** developer'a **güven** + insanların derin try-catch alışkanlığını bozmamak
(sözdizimini tanıdık tut, içgüdüye dokunma). Hatalar zaten çoğunlukla FFI, bellek
dolması ve derleyici-içi durumlardan doğar; her çağrıyı işaretlemenin bedeli faydadan
büyük.
> Not: Bu, `Type?` (explicit nullable) ile **bilinçli** felsefi ayrışmadır — null
> *tipte* görünür, ama hata akışı *blok* düzeyinde tanıdık tutulur. Reddedilen (i):
> Swift/Zig'in imza-işaretli + çağrıda `try f()` modeli.
### Stacktrace mekaniği (modelden bağımsız önkoşul)
- Her `CallFrame``IRFunction` + komut işaretçisi; **IR'a satır tablosu**
(komut index → kaynak konum) eklenir (önce taşıyıp taşımadığı doğrulanmalı).
- panic/throw'da frame stack gezilir → `fonksiyon + konum`, en içten dışa → `trace`.
- Sunum: derleme-zamanı diagnostic ile **aynı kabuk** (kod + mesaj + konum +
"nasıl düzelt" #20), hem insan hem **JSON** (toolbox: her hata yapılandırılmış nesne).
- Farklılaştırıcı: deterministik → trace'e adım indeksi → hataya **geri sar**.
### İlişkili güncellemeler
- **ADR-014 "tuple yok" → "tuple ERTELENDİ"** (reddedilmedi; çoklu-dönüş kodu
spagettileştirir, şimdilik uzak ama masada — `interface` gibi).
- **`finally` yerine ileride `defer`** (GC'li, RAII'siz dilde daha temiz). Ayrı küçük karar.
- ADR-021 ile uyum: statik analiz provable null'ı yakalar; bu hata onun backstop'u + `!`.
---
## ADR-026: Tip Dönüşümü — `as` (Skaler/String), Başarısızlık Hedef Tipinin Nullable'lığıyla
### Bağlam
ADR-010 "gizli int↔float yok" → değişken-değişken dönüşüm **açık** olmalı. float
runtime'ı var ama cast sözdizimi yoktu → int↔float dönüşümü imkânsızdı. Ayrıca
elimizde null (ADR-021) + hata (ADR-025) modelleri var; cast bunlarla örtüşmeli.
### Karar
**Sözdizimi: `as` (infix, sola-bağlı).** `deger as int`.
- Sola-bağlı olduğu için zincir **lineer** okunur: `a as int as string` =
`((a as int) as string)`, parantez gerekmez (fonksiyon-stili `int(float(a))`'nın
iç içe çirkinliği yok).
- `int(x)` fonksiyon-stili **reddedildi** ("int adlı fonksiyon mu, cast mı"
belirsizliği); C-tarzı `(int)x` ve `static_cast<>` reddedildi.
**Kapsam: yalnızca skaler + string** (`int`/`float`/`bool`/`string` arası).
- **Struct/array cast'e GİRMEZ.** Farklı struct'lar ayrı tiplerdir; "dönüşümleri"
geliştiricinin yazdığı **açık yapıcı fonksiyonlarla** olur (`Employee yap(Person p)`).
Gerekçe: yapısal/duck eşleme veya reinterpret = derleyiciyi karmaşıklaştırır +
sessiz alan kaybı = hataya açık. OOP'siz "cage" kimliğiyle uyumsuz.
**Başarısızlık davranışı = HEDEF TİPİN nullable'lığı** (ayrı `as?` operatörü YOK):
- `x as int` → hedef non-null → başarısızsa **`Error` fırlatır** (ADR-025), sonuç `int`.
- `x as int?` → hedef nullable → başarısızsa **`null` döner**, sonuç `int?`.
Nullable her zaman **tipte** (`?`) yaşar, ayrı operatör icat edilmez. Sonra `int?`'i
`int`'e çevirmek için **narrowing** (`if`) gerekir — `!`/`??` yasak (ADR-021).
### Dönüşüm matrisi
| Dönüşüm | Hatasız mı? | Not |
|---|---|---|
| `int → float` | ✅ hatasız | büyük int'te kesinlik kaybı olabilir, patlamaz |
| `int → string`, `float → string` | ✅ hatasız | biçimlendirme |
| `string → int`/`float` | ⚠️ fallible | parse; `"abc"``as int` fırlatır / `as int?` null |
| `float → int` | ⚠️ fallible | sonlu & aralık-içi: **sıfıra doğru kırpılır** (`1.71→1`, `-1.71→-1`); NaN/Inf/taşma → fırlatır / null |
| `bool ↔ int` | (karar) | başta yasak tutmak en güvenlisi; gerekirse açılır |
### Örnek (ADR-021 ile birlikte)
```
int a = 1.71 as int?; // ✗ DERLEME HATASI: int? → int (daraltma); cast başarılı olsa bile statik tip int?
int a = 1.71 as int; // ✓ a = 1 (kırpma); başarısızsa Error
int? a = 1.71 as int?; // ✓ tipler eşit
```
---
## Kararların Özet Tablosu ## Kararların Özet Tablosu
| 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; `clone()` merkezi, sembol tablosu remap edilir | | 007 | Analiz vs optimizasyon | Analiz yerinde; `ast` komutu klon üstünde dönüştürür (öncesi/sonrası karşılaştırması); `run`/`ir` yerinde optimize eder (klon yok); sembol bağları salt-okunur paylaşım (remap gerekmez) |
| 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ı; monotonluk/iterasyon-tavanı değişmezi; akışa-bağlı analiz tur başına tazelenir | | 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; tamsayı literali bağlama-göre tiplenir | | 010 | Tip sistemi | Minimal+genişletilebilir Type; gizli dönüşüm yok; Error tipi; tamsayı literali bağlama-göre tiplenir |
@ -680,3 +1128,10 @@ modelini birlikte zorlar — ikisi de bu yüzden ertelendi.
| 017 | Batteries/stdlib | Sınır problemi; küçük builtin + FFI/kütüphane; ertelendi | | 017 | Batteries/stdlib | Sınır problemi; küçük builtin + FFI/kütüphane; ertelendi |
| 018 | `interface` | Ertelendi (reddedilmedi); struct+fonksiyon yeter | | 018 | `interface` | Ertelendi (reddedilmedi); struct+fonksiyon yeter |
| 019 | Frontend↔runtime | Frontend yapı+anlam; çekirdek/cihaz/çıktı runtime'a ait | | 019 | Frontend↔runtime | Frontend yapı+anlam; çekirdek/cihaz/çıktı runtime'a ait |
| 020 | Değer/referans semantiği | Primitive=değer, bileşik (struct/array/string)=referans; "pointer yok"=`&`/`*` sözdizimi yok; kaçma/lifetime problemi bilinçli açıldı → GC borcu (#56); ADR-014'ün "GC gerekmez" sonucu iptal |
| 021 | Null güvenliği | `Type?` nullable, varsayılan non-null; akış-duyarlı null analizi (compile-time, runtime maliyeti sıfır); `!` runtime-kontrollü non-null iddiası |
| 022 | Bellek geri-kazanımı | Basit taşımasız stop-the-world mark-sweep (deterministik); nesne modeli baştan GC-hazır (header+root+child); v1 toplamasız, v2 mark-sweep; refcount kalıcı model DEĞİL; #56'nın yönü |
| 023 | Eşitlik semantiği | `==` = primitive değer / referans (struct,array) **kimlik**; deepEqual asla `==`'e bağlanmaz (ayrı `deepEquals()`); string `==` içerik (→ #40, Java gotcha'sından kaçın); `obj==obj` hata + kullanıcı-tanımlı eşitlik = uzak gelecek |
| 024 | String | Immutable değer-tipi, iç temsil **UTF-8**; `==` içerik; mutasyon yeni string üretir; bayt/scalar/grapheme açıkça ayrı; verimli birleştirme için ileride builder; #40/#9'u çözer |
| 025 | Hata yönetimi | Struct-tabanlı yakalanabilir hata (değer Swift gibi, OOP yok); standart `Error{line,col,message,trace,code}`; klasik `try{}catch{}` **unchecked** (fonksiyon işaretsiz, Java usulü); runtime null-deref/OOB yakalanabilir (esasen FFI backstop); deterministik stacktrace (IR satır tablosu); tuple→ertelendi; finally→`defer`; #57 |
| 026 | Tip dönüşümü | `as` (infix, sola-bağlı), yalnızca skaler+string; struct/array cast YOK (elle yapıcı fonksiyon); başarısızlık hedef nullable'lığıyla (`as int` fırlatır / `as int?` null); float→int kırpma; #42 |

View File

@ -0,0 +1,60 @@
# ADR-008: && ve || kısa devre değerlendirmesi
## Durum
Kabul edildi.
## Bağlam
Mevcut kodda `&&` ve `||` çalışma anında bozuk: IR üretici bu operatörler için
`case` içermiyor, `default` koluna düşüp `LOAD_CONST 0` üretiyor — yani değişken
operandlarda her zaman `false` dönüyor. Yalnızca her iki operand sabit olduğunda
sabit katlama doğru sonucu veriyor. (Kanıt: `ir_generator.cpp:395-413`,
`constant_folding.hpp:107-112`; davranış referansı bölüm B.)
## Karar
`&&` ve `||` **KISA DEVRE** değerlendirilir:
- `a && b`: `a` false ise `b` **HİÇ değerlendirilmez**, sonuç `false`.
- `a || b`: `a` true ise `b` **HİÇ değerlendirilmez**, sonuç `true`.
Bu, bu operatörlerin sıradan ikili işlem (iki tarafı hesapla sonra birleştir)
**DEĞİL**, bir dallanma olarak üretilmesi gerektiği anlamına gelir.
IR şeması:
```
a && b:
slot_a = [a değerlendir]
result = freshSlot()
LOAD_CONST result, 0 ; varsayılan: false
JIF_FALSE slot_a → DONE ; a false? b'yi atla, result=0 kalsın
slot_b = [b değerlendir]
LOAD_SLOT result, slot_b ; result = b'nin değeri
DONE:
a || b:
slot_a = [a değerlendir]
result = freshSlot()
LOAD_CONST result, 1 ; varsayılan: true
JIF_TRUE slot_a → DONE ; a true? b'yi atla, result=1 kalsın
slot_b = [b değerlendir]
LOAD_SLOT result, slot_b ; result = b'nin değeri
DONE:
```
`||` için `JIF_TRUE` opcode'u gerekir. `JIF_FALSE`'un simetriği olarak
`instruction.hpp`'e ve `interpreter.cpp`'e eklendi. `do-while` döngüsünün
mevcut `EQUAL_EQUAL(cond, 1)` geçici çözümü bu opcode'dan faydalanabilir
(ayrı düzeltme — bu ADR kapsamı dışı).
## Gerekçe
- C-ailesi dillerin (C, Go, Java, JS, C#) tamamı kısa devre yapar; hedef kitle
bunu bekler.
- Performans artısı: gereksiz sağ-taraf değerlendirmesi atlanır; kısa devre
OLMAYAN versiyon her iki tarafı da her zaman hesaplayacağı için daha yavaştır.
- Niş ile uyumlu: derleyici "şu çağrı şu durumda atlandı" diye gösterebilir.
## Sonuçlar
- Tek dezavantaj: mantıksal operatörün sağındaki yan etki koşullu çalışır.
Bu kabul edilir; yan etkiyi koşula gömmek zaten kötü kalıptır.
- Sabit katlama yolu (`constant_folding.hpp`) zaten doğru çalışıyordu ve
değiştirilmedi; bu düzeltme yalnızca değişken-operand (IR üretim) yolunu etkiler.

225
docs/architecture.md Normal file
View File

@ -0,0 +1,225 @@
# saQut — Mimari Referans
**Programlanabilir, incelenebilir bir derleyici — bir "alet çantası" (toolbox).**
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.
---
## Tasarım felsefesi — neden saQut farklı?
saQut "daha iyi bir dil" iddiasında değil. Farkı, **derleyiciyi bir platform**
olarak ele almasında. İki taahhüt üstüne kuruludur:
**1. Cam (gör + sorgula + içine müdahale et).** Her aşama — token, AST, sembol
tablosu, tip, IR — kararlı, makine-okur ve **çift yönlü** bir arayüzden
erişilebilir olmalıdır. Sadece "dök ve göster" değil: kendi AST'ini verip tip
kontrolü isteyebilmeli, IR verip çalıştırabilmelisin. **Turnusol testi:** bir
yabancı, yalnızca `saqut ast` + `saqut symbols` çıktısından, bizden habersiz bir
LSP yazabiliyor mu? Cevap "evet" ise platform gerçektir.
**2. Kafes (deterministik + yetenek-güvenli çalıştırma).** Pointer yok, value
semantics, scope-tabanlı bellek ve **tek dış-dünya kapısı olan FFI seam**
(ADR-016) sayesinde saQut kodu, host'un açıkça izin verdiği fonksiyonlar dışında
dünyaya dokunamaz. Bytecode VM deterministiktir (ADR-015): aynı girdi → aynı
çıktı → aynı çalışma. "Sadelik" diye tasarlanan bu kararlar aslında bir
**yetenek-güvenliği (capability sandbox)** kurar — güvenilmeyen veya
AI-üretimi kodu güvenle çalıştırmak için biçilmiş kaftan.
**Bu ikisinin ödülü — kayıt & tekrar (record-replay).** 🚧 *(vizyon, v0 değil;
bkz. issue #94.)* Belirsizliğin tek kaynağı (kullanıcı girdisi, zaman, IO,
GC/thread kararları) FFI kapısından geçtiği için, mükemmel tekrar oynatma için
**her değişkeni her adımda kaydetmek gerekmez** — yalnızca kapıdan geçen değerler
kaydedilir, gerisi VM deterministik olarak yeniden çalıştırılarak üretilir. Boyut
gigabayttan kilobayta düşer. Replay modunda FFI çağrıları gerçekten çalışmaz,
kaydedilmiş değeri döndürür (dosyayı tekrar silmez, sunucuya tekrar istek atmaz).
Böylece "benim makinemde çalışıyor, müşteride patlıyor" sorunu: müşteri bir dump
yollar, sen çöküşü adım adım, aynı verilerle geri sararsın.
> Log, önceden sormayı akıl ettiğin sorulara cevap verir; **tekrar-oynatma,
> çöküşten *sonra* aklına gelen sorulara.** Zaman-yolculuğu hata ayıklama ayrı
> bir altyapı değildir — cam sorgularına bir **zaman koordinatı** eklemektir.
⚠️ Bu ödülün bedeli v0'da ödenir: **determinizm kutsaldır ve her belirsizlik
kaynağı kayıt-altına-alınabilir tek kapıdan geçmelidir.** Sonradan eklenemez;
baştan korunur.
---
## Mimari hatlar
```
KAYNAK KOD
│ lexer
TOKEN'LAR ────────────── saqut tokens
│ parser (Pratt + recursive descent)
AST ──────────────────── saqut ast
│ sembol toplama (iki geçişli) ┐
▼ │
SEMBOL TABLOSU ───────── saqut symbols │ FRONTEND
│ semantik analiz (annotation) │ (yapı + anlam)
▼ │
ANNOTATE EDİLMİŞ AST ─── saqut ast ┘
│ optimizasyon (opsiyonel, klon üstünde) ── MIDDLE-END
IR ───────────────────── (planlanan) ┐
│ bytecode VM / yorumlayıcı döngü │ BACKEND
▼ │ (çalıştırma + FFI seam)
ÇALIŞTIRMA / ÇIKTI ───── saqut run ┘
```
- **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.
---
## CLI (mevcut + planlanan)
```
# --- çalışıyor ---
saqut tokens file:kaynak.sqt # token listesi
saqut ast file:kaynak.sqt # AST (JSON)
saqut symbols file:kaynak.sqt # sembol tablosu (iskelet)
# --- planlanan ---
saqut run file:kaynak.sqt # IR üret + bytecode VM ile çalıştır
saqut ast file:kaynak.sqt --optimized # klon, optimize edilmiş AST (öncesi/sonrası)
saqut transpile file:kaynak.sqt -o prog.c # ikinci backend (ileride)
```
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.
---
## Batteries / stdlib — kuzey yıldızı, ertelendi
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.**
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.
- **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).
---
## Belge haritası
| 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 |
---
## İlke
Bir şey çalışmadan önce çerçeve inşa etmekten kaçın. Önce **uçtan uca tek bir
dikey dilim** çalıştır (kaynak → IR → çalıştır; tamsayı aritmetiği + değişken +
kontrol akışı + tek bir `print`). Modülerlik bir kuzey yıldızıdır, v0.1
gereksinimi değil; ihtiyaç doğmadan eklenen her soyutlama **daha az değil, daha
çok** karmaşıklıktır.

View File

@ -18,9 +18,10 @@
> **çok uzak gelecektir**. ADR-001'deki karşılaştırmalar o gün için geçerli. > **ç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 > - "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). > 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 > - **Yapılan vs planlanan:** Tüm pipeline uygulandı. `examples/fibonacci.sqt`
> (lexer/tokenizer/parser/AST + minimal IR deneyi çalışır); kod üretimi ve VM > uçtan uca çalışıyor (lexer → tokenizer → parser → sembol tablosu → tip
> **henüz yoktur.** > denetleyici → optimizasyon → IR üreteci → bytecode VM). ADR-001'deki
> "mevcut durum" listesi artık tarihseldir; güncel durum için bkz. `CLAUDE.md`.
--- ---

View File

@ -10,21 +10,12 @@
> 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, > ✅ **Birinci kilometre taşı AŞILDI.** Faz 04 uygulandı; `examples/fibonacci.sqt`
> AST, AST'nin JSON serileştirmesi, CLI iskeleti, konum takibi, basit aritmetiği > uçtan uca çalışıyor. Bu yol haritası artık tarihsel bir referanstır.
> 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), > **Sonraki hedefler:** float/double codegen, struct IR, array IR, açık bug'lar
> hedef **"fibonacci'yi derle ve çalıştır"** (`examples/fibonacci.sqt`). Faz 01 > (#35 bellek sızıntısı, #36 W003 uyarısı, #37 `%=` IR, #38 global değişken IR).
> bunun önkoşuludur. > Güncel "çalışıyor / henüz yok" listesi için bkz. `CLAUDE.md`.
>
> 🧭 **Ö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 03 fibonacci'yi geçirdikten **sonra** anlam kazanır — erken
> soyutlama daha az değil, daha çok karmaşıklıktır.
--- ---
@ -46,7 +37,7 @@ Katman eşlemesi (ADR-006):
--- ---
## Faz 0 — Temeller (Type + Diagnostic + Hata Kataloğu) ## Faz 0 — Temeller (Type + Diagnostic + Hata Kataloğu) — TAMAMLANDI
**Bağımlılık:** yok. **Hedef:** her şeyin üstüne kurulacağı temel veri yapıları. **Bağımlılık:** yok. **Hedef:** her şeyin üstüne kurulacağı temel veri yapıları.
İlgili ADR: 010 (Type), 013 (Diagnostic). İlgili ADR: 010 (Type), 013 (Diagnostic).
@ -91,7 +82,7 @@ Katman eşlemesi (ADR-006):
--- ---
## Faz 1 — AST Refactor (ExpressionNode / StatementNode + analiz alanları) ## Faz 1 — AST Refactor (ExpressionNode / StatementNode + analiz alanları) — TAMAMLANDI
**Bağımlılık:** Faz 0 (Type). **Hedef:** node hiyerarşisini ifade/deyim olarak **Bağımlılık:** Faz 0 (Type). **Hedef:** node hiyerarşisini ifade/deyim olarak
ayır, analiz alanlarını ekle. İlgili ADR: 012, 013. ayır, analiz alanlarını ekle. İlgili ADR: 012, 013.
@ -116,7 +107,7 @@ ayır, analiz alanlarını ekle. İlgili ADR: 012, 013.
--- ---
## Faz 2 — Symbol Table (scope'lu, iki-geçişli toplama) ## Faz 2 — Symbol Table (scope'lu, iki-geçişli toplama) — TAMAMLANDI
**Bağımlılık:** Faz 0, 1. **Hedef:** isim çözümleme + scope + referans toplama. **Bağımlılık:** Faz 0, 1. **Hedef:** isim çözümleme + scope + referans toplama.
İlgili ADR: 011, 013. İlgili ADR: 011, 013.
@ -150,7 +141,7 @@ ayır, analiz alanlarını ekle. İlgili ADR: 012, 013.
--- ---
## Faz 3 — Semantic Analiz (Tip Kontrolü + Yapısal Doğrulama) ## Faz 3 — Semantic Analiz (Tip Kontrolü + Yapısal Doğrulama) — TAMAMLANDI
**Bağımlılık:** Faz 2. **Hedef:** tipleri ata/kontrol et, yapısal kuralları **Bağımlılık:** Faz 2. **Hedef:** tipleri ata/kontrol et, yapısal kuralları
doğrula. İlgili ADR: 010, 013. doğrula. İlgili ADR: 010, 013.
@ -173,7 +164,7 @@ doğrula. İlgili ADR: 010, 013.
--- ---
## Faz 4 — Optimizasyon Framework ## Faz 4 — Optimizasyon Framework — TAMAMLANDI
**Bağımlılık:** Faz 3. **Hedef:** opsiyonel, iteratif, toggle'lı kaynak-seviyesi **Bağımlılık:** Faz 3. **Hedef:** opsiyonel, iteratif, toggle'lı kaynak-seviyesi
optimizasyon. **Orijinali bozmaz — klon üstünde** (ADR-007). İlgili ADR: 007, 008, 009. optimizasyon. **Orijinali bozmaz — klon üstünde** (ADR-007). İlgili ADR: 007, 008, 009.

186
docs/sonnet-handoff.md Normal file
View File

@ -0,0 +1,186 @@
# 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.

25
examples/test_bitwise.sqt Normal file
View File

@ -0,0 +1,25 @@
int global_x = 10;
int global_y = 3;
int main() {
// global değişken testi (#38)
print(global_x);
print(global_y);
// bitsel AND, OR, SHL, SHR (#45)
int a = 12;
int b = 10;
print(a & b);
print(a | b);
print(1 << 3);
print(16 >> 2);
// unary ~ ve !
int c = 0;
print(!c);
int d = 5;
print(!d);
print(~0);
return 0;
}

347
readme.md
View File

@ -1,225 +1,186 @@
# saQut # saQut
**Programlanabilir, incelenebilir bir derleyici — bir "alet çantası" (toolbox).** > **A compiler built as a toolbox, not a black box —**
> every internal phase is a first-class, inspectable output.
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, saqut tokens file:fib.sqt → token stream, JSON
AST, sembol tablosu, optimizasyonun öncesi/sonrası ve IR — hepsi ayrı ayrı saqut ast file:fib.sqt → full AST, JSON
incelenebilir. Dil, bu aletin üzerinde çalıştığı küçük, prosedürel bir saqut ast file:fib.sqt --optimized → constant-folded + DCE'd AST
örnektir; vitrin değil, alet. saqut run file:fib.sqt → execute via IR + bytecode VM
```
Uygulama dili **C++**'tır (header-only eğilimli, bkz. `docs/fikirler.md` ADR-003). Most compilers are black boxes. saQut is a **glass box.**
--- ---
## Şu an ne çalışıyor, ne çalışmıyor ## What is it?
Belgeler **planlanan** ile **yapılan**ı net ayırır. Bugünkü gerçek durum: saQut is a **procedural language compiler** written in C++.
The language is small and C-flavoured on purpose — it is a vehicle, not the product.
The product is **a compilation pipeline where every stage is named, queryable, and machine-readable.**
### ✅ Çalışıyor (built) You can pipe `saqut ast` into your own tool.
- **Lexer** — karakter seviyesi tarama, konum takibi. You can hand the optimized AST diff to a review script.
- **Tokenizer** — token üretimi (6 token tipi), yorum satırı desteği. A stranger with no access to source could write an LSP from `saqut symbols` output alone.
- **Pratt parser** — ifade (Pratt) + statement (recursive descent) ayrıştırma. That is the test saQut is designed to pass.
- **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) ## The language looks like this
Prosedürel, **C ailesi sözdizimi**, **value semantics**. İlk ifade doğrudan bir ```c
işlem/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);
}
| Özellik | Karar | 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));
print(fibonacciIterative(n));
return 0;
}
```
- No mandatory `class` / `main` boilerplate
- Typed functions, `struct`, `int[]` arrays
- `int`, `float`, `bool`, `string` literal types
- Value semantics — no user-visible pointers
- Single FFI seam (`callhost`) — the only door to the outside world
**Deliberately absent:** OOP, closures, generics, implicit int↔float coercion, `auto`.
---
## Build
**Requirements:** C++17, CMake ≥ 3.16, Ninja
```bash
git clone https://github.com/abdussamedulutas/saqut
cd saqut
cmake -B build -G Ninja
cmake --build build
```
Binary lands at `build/saqut`.
**Tested on:** Linux (x86-64, Manjaro). macOS and Windows untested but no platform-specific code.
---
## CLI
| Command | What you get |
|---|---| |---|---|
| Class / OOP / kalıtım | **Yok** | | `saqut tokens file:src.sqt` | Token stream with positions |
| Closure | **Yok** | | `saqut ast file:src.sqt` | Full AST as JSON |
| Generic | **Yok** | | `saqut ast file:src.sqt --optimized` | AST after constant folding + dead-code elimination |
| Kullanıcıya açık pointer (`*` / `&`) | **Yok** — derleyici/runtime içeride pointer'ı serbestçe kullanır | | `saqut symbols file:src.sqt` | Symbol table dump |
| `struct` | **Var** | | `saqut check file:src.sqt` | Semantic analysis only — errors and warnings, JSON |
| Tipli fonksiyonlar (dönüş + parametre) | **Var** | | `saqut ir file:src.sqt` | IR instruction dump |
| Array (`int[]`) | **Var** | | `saqut run file:src.sqt` | Compile and run via bytecode VM |
| `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 Every output is designed to be piped, diffed, or consumed by other tools.
(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 ## Pipeline
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.
---
## Tasarım felsefesi — neden saQut farklı?
saQut "daha iyi bir dil" iddiasında değil. Farkı, **derleyiciyi bir platform**
olarak ele almasında. İki taahhüt üstüne kuruludur:
**1. Cam (gör + sorgula + içine müdahale et).** Her aşama — token, AST, sembol
tablosu, tip, IR — kararlı, makine-okur ve **çift yönlü** bir arayüzden
erişilebilir olmalıdır. Sadece "dök ve göster" değil: kendi AST'ini verip tip
kontrolü isteyebilmeli, IR verip çalıştırabilmelisin. **Turnusol testi:** bir
yabancı, yalnızca `saqut ast` + `saqut symbols` çıktısından, bizden habersiz bir
LSP yazabiliyor mu? Cevap "evet" ise platform gerçektir.
**2. Kafes (deterministik + yetenek-güvenli çalıştırma).** Pointer yok, value
semantics, scope-tabanlı bellek ve **tek dış-dünya kapısı olan FFI seam**
(ADR-016) sayesinde saQut kodu, host'un açıkça izin verdiği fonksiyonlar dışında
dünyaya dokunamaz. Bytecode VM deterministiktir (ADR-015): aynı girdi → aynı
çıktı → aynı çalışma. "Sadelik" diye tasarlanan bu kararlar aslında bir
**yetenek-güvenliği (capability sandbox)** kurar — güvenilmeyen veya
AI-üretimi kodu güvenle çalıştırmak için biçilmiş kaftan.
**Bu ikisinin ödülü — kayıt & tekrar (record-replay).** 🚧 *(vizyon, v0 değil;
bkz. issue #94.)* Belirsizliğin tek kaynağı (kullanıcı girdisi, zaman, IO,
GC/thread kararları) FFI kapısından geçtiği için, mükemmel tekrar oynatma için
**her değişkeni her adımda kaydetmek gerekmez** — yalnızca kapıdan geçen değerler
kaydedilir, gerisi VM deterministik olarak yeniden çalıştırılarak üretilir. Boyut
gigabayttan kilobayta düşer. Replay modunda FFI çağrıları gerçekten çalışmaz,
kaydedilmiş değeri döndürür (dosyayı tekrar silmez, sunucuya tekrar istek atmaz).
Böylece "benim makinemde çalışıyor, müşteride patlıyor" sorunu: müşteri bir dump
yollar, sen çöküşü adım adım, aynı verilerle geri sararsın.
> Log, önceden sormayı akıl ettiğin sorulara cevap verir; **tekrar-oynatma,
> çöküşten *sonra* aklına gelen sorulara.** Zaman-yolculuğu hata ayıklama ayrı
> bir altyapı değildir — cam sorgularına bir **zaman koordinatı** eklemektir.
⚠️ Bu ödülün bedeli v0'da ödenir: **determinizm kutsaldır ve her belirsizlik
kaynağı kayıt-altına-alınabilir tek kapıdan geçmelidir.** Sonradan eklenemez;
baştan korunur.
---
## Mimari hatlar
``` ```
KAYNAK KOD Source
│ lexer │ Lexer + Tokenizer
TOKEN'LAR ────────────── saqut tokens Tokens ──────────────────── saqut tokens
│ parser (Pratt + recursive descent) │ Pratt parser + recursive descent
AST ──────────────────── saqut ast AST ─────────────────────── saqut ast
│ sembol toplama (iki geçişli) ┐ │ Symbol collector (two-pass)
▼ │
SEMBOL TABLOSU ───────── saqut symbols │ FRONTEND Symbol Table ────────────── saqut symbols
│ semantik analiz (annotation) │ (yapı + anlam) │ Type checker + structural validator
▼ │
ANNOTATE EDİLMİŞ AST ─── saqut ast ┘ Annotated AST
│ optimizasyon (opsiyonel, klon üstünde) ── MIDDLE-END │ Optimization Manager (clone — original untouched)
│ ├─ Constant Folding pass
IR ───────────────────── (planlanan) ┐ │ └─ Dead Code Elimination pass
│ bytecode VM / yorumlayıcı döngü │ BACKEND
▼ │ (çalıştırma + FFI seam) Optimized AST ───────────── saqut ast --optimized
ÇALIŞTIRMA / ÇIKTI ───── saqut run ┘ │ IR Generator
IR ──────────────────────── saqut ir
│ Bytecode VM (interpreter loop)
Output ──────────────────── saqut run
``` ```
- **Frontend** yapıyı ve anlamı modeller (tip, scope, dataflow). The optimizer works on a **clone** of the AST — the original is preserved.
- **"Hangi çekirdek, hangi cihaz, ne zaman, hangi çıktı formatı"** runtime/backend Constant folding and DCE run in a fixpoint loop until nothing changes.
meselesidir — frontend'e yüklenmez.
--- ---
## CLI (mevcut + planlanan) ## What works right now
``` | Stage | Status |
# --- çalışıyor ---
saqut tokens file:kaynak.sqt # token listesi
saqut ast file:kaynak.sqt # AST (JSON)
saqut symbols file:kaynak.sqt # sembol tablosu (iskelet)
# --- planlanan ---
saqut run file:kaynak.sqt # IR üret + bytecode VM ile çalıştır
saqut ast file:kaynak.sqt --optimized # klon, optimize edilmiş AST (öncesi/sonrası)
saqut transpile file:kaynak.sqt -o prog.c # ikinci backend (ileride)
```
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.
---
## Batteries / stdlib — kuzey yıldızı, ertelendi
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.**
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.
- **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).
---
## Belge haritası
| Belge | İçerik |
|---|---| |---|---|
| `docs/fikirler.md` | ADR-001…005: backend stratejisi, parser, header-only, token, IR | | Lexer / Tokenizer | ✅ |
| `docs/adr-frontend-analiz.md` | ADR-006…019: frontend, analiz/optimizasyon, çalıştırma modeli, FFI, interface, bellek | | Pratt parser | ✅ |
| `docs/roadmap-frontend.md` | Faz-faz uygulama planı (sembol tablosu → fibonacci) | | AST + JSON serialization | ✅ |
| `docs/transkript-frontend-tasarim.md` | Tasarım oturumunun transkripti | | Symbol table (two-pass collector) | ✅ |
| `examples/fibonacci.sqt` | Geçerli referans program (semantik + kod üretimi fixture'ı) | | Type checker | ✅ |
| `examples/parser-stress/` | Yalnızca parser'ı zorlayan, **geçerli olmayan** fixture'lar | | Structural validator | ✅ |
| Constant folding (int, bool, logical, unary) | ✅ |
| Dead code elimination | ✅ |
| IR generator + bytecode VM | ✅ |
| `saqut run` executes fibonacci | ✅ |
| `string` type | ✅ |
| `struct` | 🚧 |
| `int[]` arrays | 🚧 |
| Standard library / FFI beyond `print` | 🚧 |
--- ---
## İlke ## Philosophy in two sentences
Bir şey çalışmadan önce çerçeve inşa etmekten kaçın. Önce **uçtan uca tek bir **Glass:** every compilation stage is a stable, queryable output — tokens, AST, symbols, IR — all separately inspectable and pipeable.
dikey dilim** çalıştır (kaynak → IR → çalıştır; tamsayı aritmetiği + değişken + **Cage:** no user pointers, value semantics, single FFI door — the VM is deterministic, which makes record-replay and time-travel debugging a natural extension, not an afterthought.
kontrol akışı + tek bir `print`). Modülerlik bir kuzey yıldızıdır, v0.1
gereksinimi değil; ihtiyaç doğmadan eklenen her soyutlama **daha az değil, daha The long version is in [`docs/architecture.md`](docs/architecture.md).
çok** karmaşıklıktır.
---
## Design records
Architectural decisions live in `docs/`:
| File | Coverage |
|---|---|
| [`docs/fikirler.md`](docs/fikirler.md) | ADR-001005: backend strategy, parser, header-only, token, IR |
| [`docs/adr-frontend-analiz.md`](docs/adr-frontend-analiz.md) | ADR-006019: analysis, optimization, execution model, FFI, memory |
| [`docs/roadmap-frontend.md`](docs/roadmap-frontend.md) | Phase-by-phase implementation plan |
| [`docs/architecture.md`](docs/architecture.md) | Full architecture reference (Turkish) |
---
## License
Source-available, commercial use restricted.
Free for: personal use, learning, writing and running saQut programs, internal tooling.
Requires permission for: hosting as a service, embedding sub-components commercially, redistributing as a product.
See [`LICENSE.md`](LICENSE.md) for the full terms.
Commercial licensing: saqutsoftware+gitea@gmail.com

View File

@ -7,8 +7,12 @@
#include "parser/parser.hpp" #include "parser/parser.hpp"
#include "symbol/symbol_table.hpp" #include "symbol/symbol_table.hpp"
#include "symbol/symbol_collector.hpp" #include "symbol/symbol_collector.hpp"
#include "semantic/type_checker.hpp"
#include "semantic/structural_validator.hpp"
#include "diagnostic/diagnostic_engine.hpp" #include "diagnostic/diagnostic_engine.hpp"
#include "ir/ir_generator.hpp" #include "ir/ir_generator.hpp"
#include "core/config.hpp"
#include "opt/optimization_manager.hpp"
inline int cmdIr(const CliArgs& args) { inline int cmdIr(const CliArgs& args) {
std::string filePath = inputFilePath(args); std::string filePath = inputFilePath(args);
@ -29,6 +33,8 @@ inline int cmdIr(const CliArgs& args) {
SymbolTable symbolTable; SymbolTable symbolTable;
DiagnosticEngine diag; DiagnosticEngine diag;
SymbolCollector(symbolTable, diag).collect(ast); SymbolCollector(symbolTable, diag).collect(ast);
TypeChecker(symbolTable, diag).check(ast);
StructuralValidator(diag).validate(ast);
if (diag.hasErrors()) { if (diag.hasErrors()) {
diag.printAll(std::cerr); diag.printAll(std::cerr);
@ -37,9 +43,18 @@ inline int cmdIr(const CliArgs& args) {
return 1; return 1;
} }
// --optimized: constant folding + DCE yerinde uygulanır, klon yok.
// IR dump için tek versiyon yeterli — ast komutu gibi karşılaştırma yok.
if (args.optimized) {
CompilerConfig cfg;
DiagnosticEngine optDiag;
OptimizationManager(cfg, optDiag).runPassesInPlace(ast, &symbolTable);
if (optDiag.errorCount() + optDiag.warningCount() > 0)
optDiag.printAll(std::cerr); // W002 vb. uyarılar stderr'e
}
IRGenerator irGenerator; IRGenerator irGenerator;
IRProgram program = irGenerator.generate(ast, symbolTable); IRProgram program = irGenerator.generate(ast, symbolTable);
program.dump(); program.dump();
delete ast; delete ast;

View File

@ -2,12 +2,11 @@
// saQut CLI — run komutu // saQut CLI — run komutu
// //
// Tam derleme + çalıştırma pipeline'ı: // Tam derleme + çalıştırma pipeline'ı:
// tokenize → parse → sembol topla → IR üret → VM çalıştır // tokenize → parse → sembol topla → [opsiyonel: optimize] → IR üret → VM çalıştır
// //
// Başarı kriteri: // --optimized bayrağı: AST yerinde optimize edilir (klon yok — sadece tek versiyon
// build/saqut run file:examples/fibonacci.sqt // gerekiyor). ast komutu orijinali saklaması gerektiği için klon kullanır; run/ir
// → 55 // kullanmaz. Aynı pattern ir.hpp'de de var — paralel değişikliklerde ikisine bak.
// → 55
// ============================================================================ // ============================================================================
#ifndef SAQUT_CLI_RUN #ifndef SAQUT_CLI_RUN
@ -22,6 +21,8 @@
#include "semantic/type_checker.hpp" #include "semantic/type_checker.hpp"
#include "semantic/structural_validator.hpp" #include "semantic/structural_validator.hpp"
#include "diagnostic/diagnostic_engine.hpp" #include "diagnostic/diagnostic_engine.hpp"
#include "core/config.hpp"
#include "opt/optimization_manager.hpp"
#include "ir/ir_generator.hpp" #include "ir/ir_generator.hpp"
#include "vm/interpreter.hpp" #include "vm/interpreter.hpp"
@ -43,7 +44,7 @@ inline int cmdRun(const CliArgs& args) {
return 1; return 1;
} }
// ── Aşama 3: Sembol toplama ─────────────────────────────────────────── // ── Aşama 3: Sembol toplama + semantik analiz ─────────────────────────
// Identifier'ların resolvedSymbol'ü doldurulur — IR generator buna ihtiyaç duyar. // Identifier'ların resolvedSymbol'ü doldurulur — IR generator buna ihtiyaç duyar.
SymbolTable symbolTable; SymbolTable symbolTable;
DiagnosticEngine diag; DiagnosticEngine diag;
@ -59,11 +60,22 @@ inline int cmdRun(const CliArgs& args) {
return 1; return 1;
} }
// ── Aşama 4: IR üretimi ─────────────────────────────────────────────── // ── Aşama 4 (opsiyonel): Optimizasyon ────────────────────────────────
// --optimized: constant folding + DCE yerinde uygulanır, klon yok.
// Tek versiyon (optimize edilmiş) yeterli — ast komutu gibi karşılaştırma yok.
if (args.optimized) {
CompilerConfig cfg;
DiagnosticEngine optDiag;
OptimizationManager(cfg, optDiag).runPassesInPlace(ast, &symbolTable);
if (optDiag.errorCount() + optDiag.warningCount() > 0)
optDiag.printAll(std::cerr); // W002 (derleme zamanı sıfıra bölme) vb.
}
// ── Aşama 5: IR üretimi ───────────────────────────────────────────────
IRGenerator irGenerator; IRGenerator irGenerator;
IRProgram program = irGenerator.generate(ast, symbolTable); IRProgram program = irGenerator.generate(ast, symbolTable);
// ── Aşama 5: VM çalıştırma ──────────────────────────────────────────── // ── Aşama 6: VM çalıştırma ────────────────────────────────────────────
int exitCode = 0; int exitCode = 0;
try { try {
Interpreter vm(program); Interpreter vm(program);

View File

@ -73,6 +73,7 @@ struct Type {
std::shared_ptr<Type> returnType; // kind == Function std::shared_ptr<Type> returnType; // kind == Function
std::vector<Type> paramTypes; // kind == Function std::vector<Type> paramTypes; // kind == Function
std::string structName; // kind == Struct std::string structName; // kind == Struct
bool nullable = false; // ADR-021: Type? sözdizimi
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //
// Factory'ler // Factory'ler
@ -132,11 +133,26 @@ struct Type {
prim == PrimitiveKind::Double); prim == PrimitiveKind::Double);
} }
bool isString() const {
return kind == TypeKind::Primitive && prim == PrimitiveKind::String;
}
// ADR-021: "null" literal tipi — yalnızca nullable değişkene atanabilir
bool isNullLiteral() const {
return kind == TypeKind::Primitive && prim == PrimitiveKind::Void && nullable;
}
// Nullable kopyası döndür
Type asNullable() const { Type t = *this; t.nullable = true; return t; }
Type asNonNull() const { Type t = *this; t.nullable = false; return t; }
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //
// equals — Yapısal eşitlik (katı; gizli dönüşüm yok, ADR-010) // equals — Yapısal eşitlik (katı; gizli dönüşüm yok, ADR-010)
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //
// Yapısal eşitlik — nullable dahil (ADR-021: int ≠ int?)
bool equals(const Type& o) const { bool equals(const Type& o) const {
if (kind != o.kind) return false; if (kind != o.kind) return false;
if (nullable != o.nullable) return false;
switch (kind) { switch (kind) {
case TypeKind::Primitive: case TypeKind::Primitive:
return prim == o.prim; return prim == o.prim;
@ -154,13 +170,14 @@ struct Type {
return true; return true;
} }
case TypeKind::Error: case TypeKind::Error:
// Error == Error: ardışık sahte hataların bastırılması tip
// denetleyicinin sorumluluğundadır (operandı Error ise hata üretme).
return true; return true;
} }
return false; // erişilemez (tüm enum değerleri kapsandı) return false;
} }
// Temel yapısal eşitlik — nullable farkını yok say (T == T? üstün çakışma için)
bool equalsBase(const Type& o) const { return asNonNull().equals(o.asNonNull()); }
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //
// İsim yardımcıları // İsim yardımcıları
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //
@ -177,10 +194,15 @@ struct Type {
return "?"; return "?";
} }
// Bir tip adından (parser tipleri string olarak tutar) primitif Type üretir. // Bir tip adından (parser tipleri string olarak tutar) Type üretir.
// Bilinen primitif değilse Error döner — bilinmeyen tip adının teşhisi // "int?" → nullable int; "int[]" → int array; bilinen değilse Error.
// (E007) çağıranın (Faz 2/3) işidir; bu fonksiyon sessizce Error verir.
static Type fromName(const std::string& n) { static Type fromName(const std::string& n) {
// Nullable soneki: "int?", "string?" vb. (ADR-021)
if (!n.empty() && n.back() == '?') {
Type base = fromName(n.substr(0, n.size() - 1));
if (!base.isError()) return base.asNullable();
return error();
}
if (n == "int") return Int(); if (n == "int") return Int();
if (n == "float") return Float(); if (n == "float") return Float();
if (n == "double") return Double(); if (n == "double") return Double();
@ -188,6 +210,11 @@ struct Type {
if (n == "string") return String(); if (n == "string") return String();
if (n == "bool") return Bool(); if (n == "bool") return Bool();
if (n == "void") return Void(); if (n == "void") return Void();
// "int[]", "float[]" vb. — suffix [] ile dizi tipi
if (n.size() > 2 && n.substr(n.size() - 2) == "[]") {
Type elem = fromName(n.substr(0, n.size() - 2));
if (!elem.isError()) return array(elem);
}
return error(); return error();
} }
@ -195,27 +222,28 @@ struct Type {
// toString — İnsan-okur ("int", "int[]", "fn(int,int)->int") // toString — İnsan-okur ("int", "int[]", "fn(int,int)->int")
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //
std::string toString() const { std::string toString() const {
std::string base;
switch (kind) { switch (kind) {
case TypeKind::Primitive: case TypeKind::Primitive:
return primName(prim); base = primName(prim); break;
case TypeKind::Array: case TypeKind::Array:
return (elementType ? elementType->toString() : "<?>") + "[]"; base = (elementType ? elementType->toString() : "<?>") + "[]"; break;
case TypeKind::Struct: case TypeKind::Struct:
return "struct " + structName; base = "struct " + structName; break;
case TypeKind::Function: { case TypeKind::Function: {
std::string s = "fn("; base = "fn(";
for (size_t i = 0; i < paramTypes.size(); ++i) { for (size_t i = 0; i < paramTypes.size(); ++i) {
if (i) s += ","; if (i) base += ",";
s += paramTypes[i].toString(); base += paramTypes[i].toString();
} }
s += ")->"; base += ")->";
s += returnType ? returnType->toString() : "<?>"; base += returnType ? returnType->toString() : "<?>";
return s; break;
} }
case TypeKind::Error: case TypeKind::Error:
return "<error>"; return "<error>";
} }
return "<?>"; return nullable ? base + "?" : base;
} }
// ------------------------------------------------------------------ // // ------------------------------------------------------------------ //

View File

@ -20,6 +20,7 @@
// LESS/LEQ/... : dest, left, right (sonuç: 1=doğru, 0=yanlış) // LESS/LEQ/... : dest, left, right (sonuç: 1=doğru, 0=yanlış)
// JMP : jumpTarget // JMP : jumpTarget
// JIF_FALSE : cond, jumpTarget // JIF_FALSE : cond, jumpTarget
// JIF_TRUE : cond, jumpTarget
// CALL : dest, functionName, argSlots // CALL : dest, functionName, argSlots
// RETURN : src // RETURN : src
// CALLHOST : functionName, argSlots // CALLHOST : functionName, argSlots
@ -41,6 +42,7 @@ enum class Opcode {
// Örnek: LOAD_CONST dest=3 val=10 → slot[3] = 10 // Örnek: LOAD_CONST dest=3 val=10 → slot[3] = 10
LOAD_STRING, // slots[dest] = stringValue (metin sabitini slota yükle) LOAD_STRING, // slots[dest] = stringValue (metin sabitini slota yükle)
LOAD_NULL, // slots[dest] = null (ADR-021: ValueKind::Null)
// Örnek: LOAD_STRING dest=2 val="Merhaba" → slot[2] = "Merhaba" // Örnek: LOAD_STRING dest=2 val="Merhaba" → slot[2] = "Merhaba"
LOAD_SLOT, // slots[dest] = slots[src] LOAD_SLOT, // slots[dest] = slots[src]
@ -54,6 +56,13 @@ enum class Opcode {
DIV, // UYARI: sıfıra bölme → runtime_error fırlatılır DIV, // UYARI: sıfıra bölme → runtime_error fırlatılır
MOD, MOD,
// --- Bitsel (tümü: slots[dest] = slots[left] OP slots[right]) ---
BAND, // slots[left] & slots[right]
BOR, // slots[left] | slots[right]
SHL, // slots[left] << slots[right]
SHR, // slots[left] >> slots[right]
BNOT, // ~slots[src] → slots[dest] (tekli operatör; src kullanır, left/right değil)
// --- Karşılaştırma (sonuç: 1 = doğru, 0 = yanlış) --- // --- Karşılaştırma (sonuç: 1 = doğru, 0 = yanlış) ---
LESS, // slots[left] < slots[right] LESS, // slots[left] < slots[right]
LESS_EQUAL, // slots[left] <= slots[right] LESS_EQUAL, // slots[left] <= slots[right]
@ -64,7 +73,8 @@ enum class Opcode {
// --- Kontrol akışı --- // --- Kontrol akışı ---
JMP, // Koşulsuz atlama: ip = jumpTarget JMP, // Koşulsuz atlama: ip = jumpTarget
JIF_FALSE, // Koşullu atlama: slots[cond] == 0 ise ip = jumpTarget JIF_FALSE, // Koşullu atlama: slots[cond] falsy ise ip = jumpTarget
JIF_TRUE, // Koşullu atlama: slots[cond] truthy ise ip = jumpTarget
// --- Fonksiyon çağrısı --- // --- Fonksiyon çağrısı ---
CALL, // Başka bir saQut fonksiyonunu çağır. CALL, // Başka bir saQut fonksiyonunu çağır.
@ -73,6 +83,47 @@ enum class Opcode {
RETURN, // Bu frame'i kapat, slots[src]'yi caller'a ilet. RETURN, // Bu frame'i kapat, slots[src]'yi caller'a ilet.
// --- Float aritmetik (#44) ---
LOAD_FLOAT, // slots[dest] = floatValue (double sabit yükle)
FADD, // slots[dest] = slots[left] + slots[right] (float)
FSUB, // slots[dest] = slots[left] - slots[right] (float)
FMUL, // slots[dest] = slots[left] * slots[right] (float)
FDIV, // slots[dest] = slots[left] / slots[right] (float; sıfır → runtime_error)
FNEG, // slots[dest] = -slots[src] (float tekli eksi)
INT_TO_FLOAT, // slots[dest] = (double)slots[src] — gizli int→float çevrimi (literal atamasında)
FLOAT_TO_INT, // slots[dest] = (int)slots[src] — açık cast (ileride: int(x))
// --- Struct (ADR-020: referans semantiği) ---
STRUCT_NEW, // slots[dest] = yeni StructObject(intValue alan sayısı); functionName = struct tipi adı
FIELD_GET, // slots[dest] = slots[src].fields[intValue] (src=nesne, intValue=alan indeksi)
FIELD_SET, // slots[dest].fields[intValue] = slots[right] (dest=nesne, intValue=alan indeksi, right=değer)
// --- Array (ADR-020: referans semantiği) ---
ARRAY_NEW, // slots[dest] = yeni ArrayObject(intValue eleman kapasitesi)
ARRAY_GET, // slots[dest] = slots[left][slots[right]] — sınır kontrolü
ARRAY_SET, // slots[dest][slots[left]] = slots[right] — sınır kontrolü (dest=dizi, left=idx, right=değer)
ARRAY_LEN, // slots[dest] = slots[src].uzunluk()
// --- Modül-düzeyi değişken erişimi ---
// "Global" değil: her değişken kendi dosyasına (modülüne) aittir.
// Başka modüller bu alana doğrudan erişemez; yalnızca export/import ile ulaşabilir.
// TODO(#modül-scope): IRFunction.moduleId eklenerek çok-modüllü derlemede
// her fonksiyonun kendi modülünün slot alanına bakması sağlanacak (bkz. TODO.md).
LOAD_GLOBAL, // slots[dest] = moduleSlots[intValue] (bu modülün modül-düzeyi değişkeni)
STORE_GLOBAL, // moduleSlots[intValue] = slots[src]
// --- String işlemleri (ADR-024: immutable değer-tipi, içerik ==) ---
STRING_CONCAT, // slots[dest] = slots[left] + slots[right] (yeni string üretir)
// --- Hata yönetimi (ADR-025: UNCHECKED try/catch/throw) ---
ENTER_TRY, // try bloğuna giriş: TryFrame'i yığına it
// dest = catch bloğundaki Error değerinin yazılacağı slot
// jumpTarget = catch bloğunun IR konumu (-1 → backpatch)
// callDepth = VM, callStack.size()'ı kayıt altına alır (unwind için)
LEAVE_TRY, // try bloğundan normal çıkış: TryFrame'i çıkar (istisna olmadı)
THROW, // slots[src] değerini fırlat → en yakın ENTER_TRY'a unwind
// Yakalanmamışsa C++ exception olarak yükseltilir
// --- Dış dünya (FFI — Foreign Function Interface) --- // --- Dış dünya (FFI — Foreign Function Interface) ---
CALLHOST, // Host (C++) fonksiyonunu çağır. Şu an sadece "print" destekli. CALLHOST, // Host (C++) fonksiyonunu çağır. Şu an sadece "print" destekli.
// Dönüş değeri yok; sadece yan etki (stdout'a yazmak gibi). // Dönüş değeri yok; sadece yan etki (stdout'a yazmak gibi).
@ -83,12 +134,35 @@ inline const char* opcodeName(Opcode op) {
switch (op) { switch (op) {
case Opcode::LOAD_CONST: return "LOAD_CONST"; case Opcode::LOAD_CONST: return "LOAD_CONST";
case Opcode::LOAD_STRING: return "LOAD_STRING"; case Opcode::LOAD_STRING: return "LOAD_STRING";
case Opcode::LOAD_NULL: return "LOAD_NULL";
case Opcode::LOAD_SLOT: return "LOAD_SLOT"; case Opcode::LOAD_SLOT: return "LOAD_SLOT";
case Opcode::ADD: return "ADD"; case Opcode::ADD: return "ADD";
case Opcode::SUB: return "SUB"; case Opcode::SUB: return "SUB";
case Opcode::MUL: return "MUL"; case Opcode::MUL: return "MUL";
case Opcode::DIV: return "DIV"; case Opcode::DIV: return "DIV";
case Opcode::MOD: return "MOD"; case Opcode::MOD: return "MOD";
case Opcode::BAND: return "BAND";
case Opcode::BOR: return "BOR";
case Opcode::SHL: return "SHL";
case Opcode::SHR: return "SHR";
case Opcode::BNOT: return "BNOT";
case Opcode::LOAD_FLOAT: return "LOAD_FLOAT";
case Opcode::FADD: return "FADD";
case Opcode::FSUB: return "FSUB";
case Opcode::FMUL: return "FMUL";
case Opcode::FDIV: return "FDIV";
case Opcode::FNEG: return "FNEG";
case Opcode::INT_TO_FLOAT: return "INT_TO_FLOAT";
case Opcode::FLOAT_TO_INT: return "FLOAT_TO_INT";
case Opcode::STRUCT_NEW: return "STRUCT_NEW";
case Opcode::FIELD_GET: return "FIELD_GET";
case Opcode::FIELD_SET: return "FIELD_SET";
case Opcode::ARRAY_NEW: return "ARRAY_NEW";
case Opcode::ARRAY_GET: return "ARRAY_GET";
case Opcode::ARRAY_SET: return "ARRAY_SET";
case Opcode::ARRAY_LEN: return "ARRAY_LEN";
case Opcode::LOAD_GLOBAL: return "LOAD_GLOBAL";
case Opcode::STORE_GLOBAL: return "STORE_GLOBAL";
case Opcode::LESS: return "LESS"; case Opcode::LESS: return "LESS";
case Opcode::LESS_EQUAL: return "LESS_EQUAL"; case Opcode::LESS_EQUAL: return "LESS_EQUAL";
case Opcode::GREATER: return "GREATER"; case Opcode::GREATER: return "GREATER";
@ -97,8 +171,13 @@ inline const char* opcodeName(Opcode op) {
case Opcode::NOT_EQUAL: return "NOT_EQUAL"; case Opcode::NOT_EQUAL: return "NOT_EQUAL";
case Opcode::JMP: return "JMP"; case Opcode::JMP: return "JMP";
case Opcode::JIF_FALSE: return "JIF_FALSE"; case Opcode::JIF_FALSE: return "JIF_FALSE";
case Opcode::JIF_TRUE: return "JIF_TRUE";
case Opcode::CALL: return "CALL"; case Opcode::CALL: return "CALL";
case Opcode::RETURN: return "RETURN"; case Opcode::RETURN: return "RETURN";
case Opcode::STRING_CONCAT: return "STRING_CONCAT";
case Opcode::ENTER_TRY: return "ENTER_TRY";
case Opcode::LEAVE_TRY: return "LEAVE_TRY";
case Opcode::THROW: return "THROW";
case Opcode::CALLHOST: return "CALLHOST"; case Opcode::CALLHOST: return "CALLHOST";
} }
return "UNKNOWN"; return "UNKNOWN";
@ -128,6 +207,9 @@ struct Instruction {
// LOAD_CONST için yüklenecek tam sayı sabiti // LOAD_CONST için yüklenecek tam sayı sabiti
int intValue = 0; int intValue = 0;
// LOAD_FLOAT için yüklenecek double sabiti (#44)
double floatValue = 0.0;
// LOAD_STRING için yüklenecek metin sabiti (tırnak işaretleri olmadan) // LOAD_STRING için yüklenecek metin sabiti (tırnak işaretleri olmadan)
std::string stringValue; std::string stringValue;

View File

@ -20,7 +20,15 @@ static const char* opSymbol(Opcode op) {
case Opcode::SUB: return "-"; case Opcode::SUB: return "-";
case Opcode::MUL: return "*"; case Opcode::MUL: return "*";
case Opcode::DIV: return "/"; case Opcode::DIV: return "/";
case Opcode::FADD: return "+.";
case Opcode::FSUB: return "-.";
case Opcode::FMUL: return "*.";
case Opcode::FDIV: return "/.";
case Opcode::MOD: return "%"; case Opcode::MOD: return "%";
case Opcode::BAND: return "&";
case Opcode::BOR: return "|";
case Opcode::SHL: return "<<";
case Opcode::SHR: return ">>";
case Opcode::LESS: return "<"; case Opcode::LESS: return "<";
case Opcode::LESS_EQUAL: return "<="; case Opcode::LESS_EQUAL: return "<=";
case Opcode::GREATER: return ">"; case Opcode::GREATER: return ">";
@ -35,6 +43,8 @@ static bool isBinaryOp(Opcode op) {
switch (op) { switch (op) {
case Opcode::ADD: case Opcode::SUB: case Opcode::MUL: case Opcode::ADD: case Opcode::SUB: case Opcode::MUL:
case Opcode::DIV: case Opcode::MOD: case Opcode::DIV: case Opcode::MOD:
case Opcode::FADD: case Opcode::FSUB: case Opcode::FMUL: case Opcode::FDIV:
case Opcode::BAND: case Opcode::BOR: case Opcode::SHL: case Opcode::SHR:
case Opcode::LESS: case Opcode::LESS_EQUAL: case Opcode::LESS: case Opcode::LESS_EQUAL:
case Opcode::GREATER: case Opcode::GREATER_EQUAL: case Opcode::GREATER: case Opcode::GREATER_EQUAL:
case Opcode::EQUAL_EQUAL: case Opcode::NOT_EQUAL: case Opcode::EQUAL_EQUAL: case Opcode::NOT_EQUAL:
@ -113,6 +123,48 @@ void IRFunction::dump() const {
} }
std::cout << ")"; std::cout << ")";
} else if (ins.opcode == Opcode::BNOT) {
std::cout << slot(ins.dest) << " = ~" << slot(ins.src);
} else if (ins.opcode == Opcode::LOAD_FLOAT) {
std::cout << slot(ins.dest) << " = " << ins.floatValue;
} else if (ins.opcode == Opcode::INT_TO_FLOAT) {
std::cout << slot(ins.dest) << " = (float)" << slot(ins.src);
} else if (ins.opcode == Opcode::FLOAT_TO_INT) {
std::cout << slot(ins.dest) << " = (int)" << slot(ins.src);
} else if (ins.opcode == Opcode::FNEG) {
std::cout << slot(ins.dest) << " = -" << slot(ins.src);
} else if (ins.opcode == Opcode::STRUCT_NEW) {
std::cout << slot(ins.dest) << " = struct<" << ins.functionName << ">[" << ins.intValue << " alan]";
} else if (ins.opcode == Opcode::FIELD_GET) {
std::cout << slot(ins.dest) << " = " << slot(ins.src) << "." << ins.intValue;
} else if (ins.opcode == Opcode::FIELD_SET) {
std::cout << slot(ins.dest) << "." << ins.intValue << " = " << slot(ins.right);
} else if (ins.opcode == Opcode::ARRAY_NEW) {
std::cout << slot(ins.dest) << " = array[" << ins.intValue << "]";
} else if (ins.opcode == Opcode::ARRAY_GET) {
std::cout << slot(ins.dest) << " = " << slot(ins.left) << "[" << slot(ins.right) << "]";
} else if (ins.opcode == Opcode::ARRAY_SET) {
std::cout << slot(ins.dest) << "[" << slot(ins.left) << "] = " << slot(ins.right);
} else if (ins.opcode == Opcode::ARRAY_LEN) {
std::cout << slot(ins.dest) << " = len(" << slot(ins.src) << ")";
} else if (ins.opcode == Opcode::LOAD_GLOBAL) {
std::cout << slot(ins.dest) << " = global[" << ins.intValue << "]";
} else if (ins.opcode == Opcode::STORE_GLOBAL) {
std::cout << "global[" << ins.intValue << "] = " << slot(ins.src);
} else if (ins.opcode == Opcode::RETURN) { } else if (ins.opcode == Opcode::RETURN) {
std::cout << slot(ins.src); std::cout << slot(ins.src);
} }

View File

@ -10,32 +10,55 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
// Error struct alan sırası (ADR-025): makeError için IR tarafından bilinir
// 0=line, 1=col, 2=message, 3=trace, 4=code
static constexpr int ERROR_FIELD_COUNT = 5;
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
// generate — Ana giriş noktası // generate — Ana giriş noktası
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
IRProgram IRGenerator::generate(ASTNode* programNode, SymbolTable& /*symbolTable*/) { IRProgram IRGenerator::generate(ASTNode* programNode, SymbolTable& symbolTable) {
IRProgram program; IRProgram program;
// ProgramNode'un her çocuğunu gez. // 0. Geçiş: struct layout haritasını sembol tablosundan al
// Bizi ilgilendiren: FunctionDecl. StructDecl/GlobalVar → TODO. structLayouts_ = symbolTable.structLayouts;
// 1. Geçiş: modül-düzeyi VariableDecl'leri topla ve kayıt et
// "Global" değil — bu dosyanın (modülün) kendi değişkenleri.
std::vector<VariableDeclNode*> globalVars;
for (ASTNode* child : programNode->getChildren()) {
if (child->kind == ASTKind::VariableDecl) {
auto* vd = (VariableDeclNode*)child;
nameToGlobal_[vd->name] = globalCount_++;
program.globalCount++;
program.globalNames.push_back(vd->name);
globalVars.push_back(vd);
}
}
// 2. Geçiş: fonksiyonları üret
for (ASTNode* child : programNode->getChildren()) { for (ASTNode* child : programNode->getChildren()) {
if (child->kind == ASTKind::FunctionDecl) { if (child->kind == ASTKind::FunctionDecl) {
// Her fonksiyon üretimi için sıfırla
nameToSlot_.clear(); nameToSlot_.clear();
nextSlot_ = 0; nextSlot_ = 0;
// IRFunction oluştur, currentFunction_ olarak işaretle
auto* fnDecl = (FunctionDeclNode*)child; auto* fnDecl = (FunctionDeclNode*)child;
IRFunction irFn(fnDecl->name, (int)fnDecl->params.size()); IRFunction irFn(fnDecl->name, (int)fnDecl->params.size());
program.addFunction(std::move(irFn)); program.addFunction(std::move(irFn));
// addFunction std::move yaptığı için pointer'ı haritadan alalım
currentFunction_ = program.findFunction(fnDecl->name); currentFunction_ = program.findFunction(fnDecl->name);
generateFunction(child); // main'in başında global değişkenlerin init ifadelerini üret
if (fnDecl->name == "main") {
for (VariableDeclNode* gv : globalVars) {
if (gv->initExpr) {
int initSlot = generateExpression(gv->initExpr);
emitStoreGlobal(initSlot, nameToGlobal_[gv->name]);
}
}
}
// Fonksiyon bitti — toplam slot sayısını kaydet generateFunction(child);
currentFunction_->slotCount = nextSlot_; currentFunction_->slotCount = nextSlot_;
} }
} }
@ -81,7 +104,7 @@ void IRGenerator::generateStatement(ASTNode* node) {
break; break;
} }
// ── Değişken bildirimi: int x = <ifade> ────────────────────────────── // ── Değişken bildirimi: int x = <ifade> / Point p; ────────────────
case ASTKind::VariableDecl: { case ASTKind::VariableDecl: {
auto* vd = (VariableDeclNode*)node; auto* vd = (VariableDeclNode*)node;
@ -90,14 +113,22 @@ void IRGenerator::generateStatement(ASTNode* node) {
registerVariable(vd->name, varSlot); registerVariable(vd->name, varSlot);
if (vd->initExpr) { if (vd->initExpr) {
// Başlatma ifadesini üret, sonucu bir slotta al
int initSlot = generateExpression(vd->initExpr); int initSlot = generateExpression(vd->initExpr);
// float/double değişkenine int sabit atama → INT_TO_FLOAT
if (initSlot != varSlot) { bool targetIsFloat = (vd->varType == "float" || vd->varType == "double");
// Sonuç başka bir slotta, değişkenin slotuna kopyala bool srcIsInt = false;
emitLoadSlot(varSlot, initSlot); if (auto* e = dynamic_cast<ExpressionNode*>(vd->initExpr))
srcIsInt = e->resolvedType.isPrimitive() && e->resolvedType.prim == PrimitiveKind::Int;
if (targetIsFloat && srcIsInt) {
int conv = freshSlot();
emitIntToFloat(conv, initSlot);
initSlot = conv;
} }
// initSlot == varSlot: LOAD_CONST doğrudan varSlot'a yazıldı, kopya gerekmez if (initSlot != varSlot) emitLoadSlot(varSlot, initSlot);
} else if (structLayouts_.count(vd->varType)) {
// Struct değişkeni: init ifadesi yoksa boş StructObject oluştur
int fc = getStructFieldCount(vd->varType);
emitStructNew(varSlot, vd->varType, fc);
} }
// Sibling VariableDecl'ler: int a, b; → children'da diğer VariableDecl'ler // Sibling VariableDecl'ler: int a, b; → children'da diğer VariableDecl'ler
@ -153,84 +184,101 @@ void IRGenerator::generateStatement(ASTNode* node) {
case ASTKind::WhileStatement: { case ASTKind::WhileStatement: {
auto* ws = (WhileStatementNode*)node; auto* ws = (WhileStatementNode*)node;
// Döngü başının konumu — geri-jump buraya gelecek
int loopStart = currentInstrIndex(); int loopStart = currentInstrIndex();
loopContextStack_.push_back({});
int condSlot = generateExpression(ws->condition); int condSlot = generateExpression(ws->condition);
int exitJump = emitJumpIfFalse(condSlot); // ileri, backpatch bekliyor int exitJump = emitJumpIfFalse(condSlot);
if (ws->body) generateStatement(ws->body); if (ws->body) generateStatement(ws->body);
// Geri-jump: hedef zaten biliniyor (loopStart) // continue → LOOP_START (hedef baştan beri biliniyor)
emitJumpUnconditional(loopStart); for (int idx : loopContextStack_.back().continueJumps)
currentFunction_->instructions[idx].jumpTarget = loopStart;
// Döngü çıkış noktası → exitJump'ı doldur emitJumpUnconditional(loopStart);
patchJump(exitJump); patchJump(exitJump); // OUT burası
// break → OUT
int outTarget = currentInstrIndex();
for (int idx : loopContextStack_.back().breakJumps)
currentFunction_->instructions[idx].jumpTarget = outTarget;
loopContextStack_.pop_back();
break; break;
} }
// ── for (init; koşul; güncelleme) { gövde } ───────────────────────── // ── for (init; koşul; güncelleme) { gövde } ─────────────────────────
// //
// Üretilen IR yapısı: // IR yapısı (continue C_LABEL'a, break OUT'a atlar):
// [init] // [init]
// LOOP_START: // LOOP_START:
// [koşul] → condSlot // [koşul] → JIF_FALSE OUT
// JIF_FALSE condSlot → LOOP_END (ileri-jump, backpatch)
// [gövde] // [gövde]
// C_LABEL:
// [güncelleme] // [güncelleme]
// JMP LOOP_START (geri-jump, hedef biliniyor) // JMP LOOP_START
// LOOP_END: // OUT:
// ───────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────
case ASTKind::ForStatement: { case ASTKind::ForStatement: {
auto* fs = (ForStatementNode*)node; auto* fs = (ForStatementNode*)node;
// Init: genellikle "int i = 0" gibi bir VariableDecl
if (fs->init) generateStatement(fs->init); if (fs->init) generateStatement(fs->init);
// Döngü başı konumu — geri-jump'ın hedefi
int loopStart = currentInstrIndex(); int loopStart = currentInstrIndex();
loopContextStack_.push_back({});
// Koşul
int condSlot = fs->condition ? generateExpression(fs->condition) : -1; int condSlot = fs->condition ? generateExpression(fs->condition) : -1;
int exitJump = (condSlot != -1) ? emitJumpIfFalse(condSlot) : -1; int exitJump = (condSlot != -1) ? emitJumpIfFalse(condSlot) : -1;
// Gövde
if (fs->body) generateStatement(fs->body); if (fs->body) generateStatement(fs->body);
// Güncelleme (ör: i = i + 1) — ifade deyimi, sonuç önemsiz // C_LABEL: güncelleme başlangıcı — continue buraya atlar
int cLabel = currentInstrIndex();
for (int idx : loopContextStack_.back().continueJumps)
currentFunction_->instructions[idx].jumpTarget = cLabel;
if (fs->update) generateExpression(fs->update); if (fs->update) generateExpression(fs->update);
// Geri-jump: hedef loopStart, zaten biliniyor
emitJumpUnconditional(loopStart); emitJumpUnconditional(loopStart);
// Döngü çıkışı → exitJump'ı doldur if (exitJump != -1) patchJump(exitJump); // OUT burası
if (exitJump != -1) patchJump(exitJump);
// break → OUT
int outTarget = currentInstrIndex();
for (int idx : loopContextStack_.back().breakJumps)
currentFunction_->instructions[idx].jumpTarget = outTarget;
loopContextStack_.pop_back();
break; break;
} }
// ── do { gövde } while (koşul) ─────────────────────────────────────── // ── do { gövde } while (koşul) ───────────────────────────────────────
case ASTKind::DoWhileStatement: { case ASTKind::DoWhileStatement: {
auto* dw = (DoWhileStatementNode*)node; auto* dw = (DoWhileStatementNode*)node;
int loopStart = currentInstrIndex(); int loopStart = currentInstrIndex();
loopContextStack_.push_back({});
if (dw->body) generateStatement(dw->body); if (dw->body) generateStatement(dw->body);
// COND_LABEL: koşul değerlendirmesi — continue buraya atlar
int condLabel = currentInstrIndex();
for (int idx : loopContextStack_.back().continueJumps)
currentFunction_->instructions[idx].jumpTarget = condLabel;
int condSlot = generateExpression(dw->condition); int condSlot = generateExpression(dw->condition);
// Koşul doğruysa geri atla (1 = doğru → atla; 0 = yanlış → devam) Instruction jit(Opcode::JIF_TRUE);
// JIF_FALSE koşul yanlışsa atlar; biz doğruysa atlamak istiyoruz. jit.cond = condSlot;
// Bu yüzden JIF_FALSE yerine "doğruysa atla" mantığı lazım. jit.jumpTarget = loopStart;
// Basit çözüm: koşulun tersini al (0→1, diğer→0) ve JIF_FALSE kullan. currentFunction_->instructions.push_back(std::move(jit));
// NOT: saQut'ta "!" operatörü yok henüz; NOT talimatı eklenebilir.
// Şimdilik: koşul slotuna bak, sıfır değilse geri atla. // break → OUT (JIF_TRUE'dan sonraki konum)
// TODO(vm-genişletme): JIF_TRUE talimatı ekle int outTarget = currentInstrIndex();
// Geçici çözüm: sabit 1 ile karşılaştır (condSlot != 0 → geri) for (int idx : loopContextStack_.back().breakJumps)
int oneSlot = freshSlot(); currentFunction_->instructions[idx].jumpTarget = outTarget;
emitLoadConst(oneSlot, 1);
int eqSlot = freshSlot(); loopContextStack_.pop_back();
emitBinaryOp(Opcode::EQUAL_EQUAL, eqSlot, condSlot, oneSlot);
int skipJump = emitJumpIfFalse(eqSlot); // koşul yanlışsa döngüden çık
emitJumpUnconditional(loopStart); // geri atla
patchJump(skipJump);
break; break;
} }
@ -244,10 +292,66 @@ void IRGenerator::generateStatement(ASTNode* node) {
break; break;
} }
case ASTKind::BreakStatement: case ASTKind::BreakStatement: {
case ASTKind::ContinueStatement: int jumpIdx = emitJumpUnconditional(-1);
// TODO(vm-genişletme): break/continue için JMP + label mekanizması gerekir if (!loopContextStack_.empty())
loopContextStack_.back().breakJumps.push_back(jumpIdx);
break; break;
}
case ASTKind::ContinueStatement: {
int jumpIdx = emitJumpUnconditional(-1);
if (!loopContextStack_.empty())
loopContextStack_.back().continueJumps.push_back(jumpIdx);
break;
}
// ── try { body } catch (Error e) { handler } (ADR-025) ────────────
case ASTKind::TryStatement: {
auto* ts = (TryStatementNode*)node;
// Catch değişkeni için slot; VM bu slota Error nesnesini yazar
int errorSlot = freshSlot();
if (!ts->catchVar.empty())
registerVariable(ts->catchVar, errorSlot);
// ENTER_TRY: catch hedefi henüz bilinmiyor (-1), sonradan patchlanır
Instruction enterTry(Opcode::ENTER_TRY);
enterTry.dest = errorSlot;
enterTry.jumpTarget = -1;
currentFunction_->instructions.push_back(std::move(enterTry));
int enterTryIdx = (int)currentFunction_->instructions.size() - 1;
// Try gövdesi
if (ts->body) generateStatement(ts->body);
// Normal çıkış: try frame'ini çıkar
Instruction leaveTry(Opcode::LEAVE_TRY);
currentFunction_->instructions.push_back(std::move(leaveTry));
// Catch bloğunu atla (normal akışta)
int jumpOverCatch = emitJumpUnconditional(-1);
// Catch etiketi: ENTER_TRY buraya atlayacak
int catchLabel = currentInstrIndex();
currentFunction_->instructions[enterTryIdx].jumpTarget = catchLabel;
// Catch gövdesi
if (ts->handler) generateStatement(ts->handler);
// Catch bitti
patchJump(jumpOverCatch);
break;
}
// ── throw <ifade>; (ADR-025) ────────────────────────────────────────
case ASTKind::ThrowStatement: {
auto* th = (ThrowStatementNode*)node;
int valSlot = th->value ? generateExpression(th->value) : freshSlot();
Instruction ins(Opcode::THROW);
ins.src = valSlot;
currentFunction_->instructions.push_back(std::move(ins));
break;
}
default: default:
break; break;
@ -270,14 +374,29 @@ int IRGenerator::generateExpression(ASTNode* node) {
switch (lit->literalType) { switch (lit->literalType) {
case LiteralType::INTEGER: { case LiteralType::INTEGER: {
int value = 0; // Float/double bağlamında tam sayı literali → LOAD_FLOAT (bağlama-göre tip, ADR-010)
if (lit->parserToken.token) bool asFloat = lit->resolvedType.isPrimitive() &&
value = std::stoi(lit->parserToken.token->token); (lit->resolvedType.prim == PrimitiveKind::Float ||
emitLoadConst(slot, value); lit->resolvedType.prim == PrimitiveKind::Double);
if (asFloat) {
double val = 0.0;
if (lit->hasDirectValue) val = (double)lit->directIntValue;
else if (lit->parserToken.token) val = std::stod(lit->parserToken.token->token);
emitLoadFloat(slot, val);
} else {
int value = 0;
if (lit->hasDirectValue) value = lit->directIntValue;
else if (lit->parserToken.token) value = std::stoi(lit->parserToken.token->token);
emitLoadConst(slot, value);
}
break; break;
} }
case LiteralType::BOOLEAN: { case LiteralType::BOOLEAN: {
int value = (lit->parserToken.token && int value = 0;
if (lit->hasDirectValue)
value = lit->directIntValue ? 1 : 0;
else
value = (lit->parserToken.token &&
lit->parserToken.token->token == "true") ? 1 : 0; lit->parserToken.token->token == "true") ? 1 : 0;
emitLoadConst(slot, value); emitLoadConst(slot, value);
break; break;
@ -301,25 +420,32 @@ int IRGenerator::generateExpression(ASTNode* node) {
currentFunction_->instructions.push_back(std::move(ins)); currentFunction_->instructions.push_back(std::move(ins));
break; break;
} }
case LiteralType::FLOAT: case LiteralType::FLOAT: {
throw std::runtime_error( double val = 0.0;
"IR üretim hatası: float literal şu an VM tarafından desteklenmiyor. " if (lit->parserToken.token)
"Tam sayı kullanın veya float desteği eklenene kadar bekleyin."); val = std::stod(lit->parserToken.token->token);
emitLoadFloat(slot, val);
break;
}
case LiteralType::BOŞ: case LiteralType::BOŞ:
throw std::runtime_error( // null literal → ValueKind::Null (ADR-021)
"IR üretim hatası: null literal şu an VM tarafından desteklenmiyor."); { Instruction ins(Opcode::LOAD_NULL); ins.dest = slot;
currentFunction_->instructions.push_back(std::move(ins)); }
break;
} }
return slot; return slot;
} }
// ── Değişken ismi: n, first, second ... ────────────────────────────── // ── Değişken ismi: n, first, second ... ──────────────────────────────
// Bu değişkenin değeri zaten bir slotta. O slotu döndür.
case ASTKind::Identifier: { case ASTKind::Identifier: {
auto* id = (IdentifierNode*)node; auto* id = (IdentifierNode*)node;
std::string name = id->parserToken.token ? id->parserToken.token->token : ""; std::string name = id->parserToken.token ? id->parserToken.token->token : "";
// Önce builtin mi? (print gibi) — identifier olarak gelen builtin fonksiyon if (isGlobal(name)) {
// çağrıları CallExpression içinde yakalanıyor, burada sadece değişken kalır int tempSlot = freshSlot();
emitLoadGlobal(tempSlot, getGlobalIndex(name));
return tempSlot;
}
return lookupVariable(name); return lookupVariable(name);
} }
@ -327,42 +453,87 @@ int IRGenerator::generateExpression(ASTNode* node) {
case ASTKind::BinaryExpression: { case ASTKind::BinaryExpression: {
auto* bin = (BinaryExpressionNode*)node; auto* bin = (BinaryExpressionNode*)node;
// Atama operatörleri: x = expr, x += expr ... // Atama operatörleri: x = expr ve a[i] = expr
// Sol taraf bir değişken, sağ taraf hesaplanır ve o değişkene yazılır.
if (bin->Operator == TokenType::EQUAL) { if (bin->Operator == TokenType::EQUAL) {
// Sağ tarafı hesapla
int rhsSlot = generateExpression(bin->Right); int rhsSlot = generateExpression(bin->Right);
// Sol taraf değişkenin slotunu bul // a[i] = val → ARRAY_SET
if (bin->Left && bin->Left->kind == ASTKind::IndexExpression) {
auto* idx = (IndexExpressionNode*)bin->Left;
int arrSlot = generateExpression(idx->object);
int idxSlot = generateExpression(idx->index);
emitArraySet(arrSlot, idxSlot, rhsSlot);
return rhsSlot;
}
// p.field = val → FIELD_SET
if (bin->Left && bin->Left->kind == ASTKind::MemberAccess) {
auto* ma = (MemberAccessNode*)bin->Left;
int objSlot = generateExpression(ma->object);
std::string structName;
if (auto* exprObj = dynamic_cast<ExpressionNode*>(ma->object))
structName = exprObj->resolvedType.structName;
int idx2 = getStructFieldIndex(structName, ma->member);
if (idx2 >= 0) emitFieldSet(objSlot, idx2, rhsSlot);
return rhsSlot;
}
auto* lhsId = (IdentifierNode*)bin->Left; auto* lhsId = (IdentifierNode*)bin->Left;
std::string varName = lhsId->parserToken.token->token; std::string varName = lhsId->parserToken.token->token;
int varSlot = lookupVariable(varName);
// Sonucu değişkenin slotuna kopyala if (isGlobal(varName)) {
if (rhsSlot != varSlot) { emitStoreGlobal(rhsSlot, getGlobalIndex(varName));
emitLoadSlot(varSlot, rhsSlot); return rhsSlot;
} }
int varSlot = lookupVariable(varName);
if (rhsSlot != varSlot) emitLoadSlot(varSlot, rhsSlot);
return varSlot; return varSlot;
} }
// Birleşik atama: += -= *= /= // Birleşik atama: += -= *= /= %= &= |= <<= >>=
// x += y ≡ x = x + y // x OP= y ≡ x = x OP y
if (bin->Operator == TokenType::PLUS_EQUAL || if (bin->Operator == TokenType::PLUS_EQUAL ||
bin->Operator == TokenType::MINUS_EQUAL || bin->Operator == TokenType::MINUS_EQUAL ||
bin->Operator == TokenType::STAR_EQUAL || bin->Operator == TokenType::STAR_EQUAL ||
bin->Operator == TokenType::SLASH_EQUAL) { bin->Operator == TokenType::SLASH_EQUAL ||
bin->Operator == TokenType::PERCENT_EQUAL ||
bin->Operator == TokenType::AMPERSAND_EQUAL ||
bin->Operator == TokenType::PIPE_EQUAL ||
bin->Operator == TokenType::LSHIFT_EQUAL ||
bin->Operator == TokenType::RSHIFT_EQUAL) {
auto* lhsId = (IdentifierNode*)bin->Left; auto* lhsId = (IdentifierNode*)bin->Left;
std::string varName = lhsId->parserToken.token->token; std::string varName = lhsId->parserToken.token->token;
int varSlot = lookupVariable(varName);
int rhsSlot = generateExpression(bin->Right); int rhsSlot = generateExpression(bin->Right);
Opcode arithOp = Opcode::ADD; Opcode arithOp = Opcode::ADD;
if (bin->Operator == TokenType::MINUS_EQUAL) arithOp = Opcode::SUB; if (bin->Operator == TokenType::MINUS_EQUAL) arithOp = Opcode::SUB;
else if (bin->Operator == TokenType::STAR_EQUAL) arithOp = Opcode::MUL; else if (bin->Operator == TokenType::STAR_EQUAL) arithOp = Opcode::MUL;
else if (bin->Operator == TokenType::SLASH_EQUAL) arithOp = Opcode::DIV; else if (bin->Operator == TokenType::SLASH_EQUAL) arithOp = Opcode::DIV;
else if (bin->Operator == TokenType::PERCENT_EQUAL) arithOp = Opcode::MOD;
else if (bin->Operator == TokenType::AMPERSAND_EQUAL) arithOp = Opcode::BAND;
else if (bin->Operator == TokenType::PIPE_EQUAL) arithOp = Opcode::BOR;
else if (bin->Operator == TokenType::LSHIFT_EQUAL) arithOp = Opcode::SHL;
else if (bin->Operator == TokenType::RSHIFT_EQUAL) arithOp = Opcode::SHR;
// string += string → STRING_CONCAT (ADR-024)
if (bin->Operator == TokenType::PLUS_EQUAL) {
if (auto* e = dynamic_cast<ExpressionNode*>(bin->Right))
if (e->resolvedType.isString()) arithOp = Opcode::STRING_CONCAT;
}
int resultSlot = freshSlot(); int resultSlot = freshSlot();
if (isGlobal(varName)) {
int currentSlot = freshSlot();
emitLoadGlobal(currentSlot, getGlobalIndex(varName));
emitBinaryOp(arithOp, resultSlot, currentSlot, rhsSlot);
emitStoreGlobal(resultSlot, getGlobalIndex(varName));
return resultSlot;
}
int varSlot = lookupVariable(varName);
emitBinaryOp(arithOp, resultSlot, varSlot, rhsSlot); emitBinaryOp(arithOp, resultSlot, varSlot, rhsSlot);
emitLoadSlot(varSlot, resultSlot); emitLoadSlot(varSlot, resultSlot);
return varSlot; return varSlot;
@ -378,8 +549,18 @@ int IRGenerator::generateExpression(ASTNode* node) {
int zeroSlot = freshSlot(); int zeroSlot = freshSlot();
emitLoadConst(zeroSlot, 0); emitLoadConst(zeroSlot, 0);
emitBinaryOp(Opcode::SUB, resultSlot, zeroSlot, operandSlot); emitBinaryOp(Opcode::SUB, resultSlot, zeroSlot, operandSlot);
} else if (bin->Operator == TokenType::BANG) {
// !x → (x == 0): sıfırsa 1, değilse 0
int zeroSlot = freshSlot();
emitLoadConst(zeroSlot, 0);
emitBinaryOp(Opcode::EQUAL_EQUAL, resultSlot, operandSlot, zeroSlot);
} else if (bin->Operator == TokenType::TILDE) {
// ~x — bitsel değil
Instruction ins(Opcode::BNOT);
ins.dest = resultSlot;
ins.src = operandSlot;
currentFunction_->instructions.push_back(std::move(ins));
} else { } else {
// Diğer unary operatörler → TODO
emitLoadSlot(resultSlot, operandSlot); emitLoadSlot(resultSlot, operandSlot);
} }
return resultSlot; return resultSlot;
@ -399,6 +580,36 @@ int IRGenerator::generateExpression(ASTNode* node) {
case TokenType::GREATER_EQUAL: return generateBinaryArithmetic(Opcode::GREATER_EQUAL, bin->Left, bin->Right); case TokenType::GREATER_EQUAL: return generateBinaryArithmetic(Opcode::GREATER_EQUAL, bin->Left, bin->Right);
case TokenType::EQUAL_EQUAL: return generateBinaryArithmetic(Opcode::EQUAL_EQUAL, bin->Left, bin->Right); case TokenType::EQUAL_EQUAL: return generateBinaryArithmetic(Opcode::EQUAL_EQUAL, bin->Left, bin->Right);
case TokenType::BANG_EQUAL: return generateBinaryArithmetic(Opcode::NOT_EQUAL, bin->Left, bin->Right); case TokenType::BANG_EQUAL: return generateBinaryArithmetic(Opcode::NOT_EQUAL, bin->Left, bin->Right);
// Bitsel operatörler
case TokenType::AMPERSAND: return generateBinaryArithmetic(Opcode::BAND, bin->Left, bin->Right);
case TokenType::PIPE: return generateBinaryArithmetic(Opcode::BOR, bin->Left, bin->Right);
case TokenType::LSHIFT: return generateBinaryArithmetic(Opcode::SHL, bin->Left, bin->Right);
case TokenType::RSHIFT: return generateBinaryArithmetic(Opcode::SHR, bin->Left, bin->Right);
// Mantıksal operatörler: kısa devre dallanmasıyla üretilir (ADR-008).
// NOT: sıradan ikili işlem değil — b, a'nın değerine göre atlanabilir.
case TokenType::AMPERSAND_AMPERSAND: {
int slotA = generateExpression(bin->Left);
int result = freshSlot();
emitLoadConst(result, 0); // varsayılan: false
int skipB = emitJumpIfFalse(slotA); // a false → b'yi atla
int slotB = generateExpression(bin->Right);
emitLoadSlot(result, slotB); // result = b
patchJump(skipB);
return result;
}
case TokenType::PIPE_PIPE: {
int slotA = generateExpression(bin->Left);
int result = freshSlot();
emitLoadConst(result, 1); // varsayılan: true
int skipB = emitJumpIfTrue(slotA); // a true → b'yi atla
int slotB = generateExpression(bin->Right);
emitLoadSlot(result, slotB); // result = b
patchJump(skipB);
return result;
}
default: { default: {
// Bilinmeyen operatör — boş slot döndür // Bilinmeyen operatör — boş slot döndür
int slot = freshSlot(); int slot = freshSlot();
@ -473,6 +684,42 @@ int IRGenerator::generateExpression(ASTNode* node) {
return resultSlot; // artırmadan önceki değer return resultSlot; // artırmadan önceki değer
} }
// ── Üye erişimi okuma: p.x ───────────────────────────────────────────
case ASTKind::MemberAccess: {
auto* ma = (MemberAccessNode*)node;
int objSlot = generateExpression(ma->object);
int destSlot = freshSlot();
// Nesnenin struct adını resolvedType üstünden al (tip denetleyici yazdı)
std::string structName;
if (auto* exprObj = dynamic_cast<ExpressionNode*>(ma->object))
structName = exprObj->resolvedType.structName;
int idx = getStructFieldIndex(structName, ma->member);
if (idx >= 0) emitFieldGet(destSlot, objSlot, idx);
return destSlot;
}
case ASTKind::ArrayLiteral: {
auto* al = (ArrayLiteralNode*)node;
int arrSlot = freshSlot();
emitArrayNew(arrSlot, (int)al->elements.size());
for (int i = 0; i < (int)al->elements.size(); i++) {
int idxSlot = freshSlot();
emitLoadConst(idxSlot, i);
int valSlot = generateExpression(al->elements[i]);
emitArraySet(arrSlot, idxSlot, valSlot);
}
return arrSlot;
}
// ── Index erişimi okuma: a[i] ─────────────────────────────────────────
case ASTKind::IndexExpression: {
auto* idx = (IndexExpressionNode*)node;
int arrSlot = generateExpression(idx->object);
int idxSlot = generateExpression(idx->index);
int destSlot = freshSlot();
emitArrayGet(destSlot, arrSlot, idxSlot);
return destSlot;
}
default: default:
// Bilinmeyen ifade türü // Bilinmeyen ifade türü
return freshSlot(); // boş slot (0 değeriyle) return freshSlot(); // boş slot (0 değeriyle)
@ -487,7 +734,52 @@ int IRGenerator::generateBinaryArithmetic(Opcode opcode, ASTNode* leftNode, ASTN
int leftSlot = generateExpression(leftNode); int leftSlot = generateExpression(leftNode);
int rightSlot = generateExpression(rightNode); int rightSlot = generateExpression(rightNode);
int destSlot = freshSlot(); int destSlot = freshSlot();
emitBinaryOp(opcode, destSlot, leftSlot, rightSlot);
// Float tip kontrolü — resolvedType üstünden (tip denetleyici tarafından yazıldı)
bool leftIsFloat = false, rightIsFloat = false;
bool leftIsString = false, rightIsString = false;
if (auto* e = dynamic_cast<ExpressionNode*>(leftNode)) {
leftIsFloat = e->resolvedType.isPrimitive() &&
(e->resolvedType.prim == PrimitiveKind::Float ||
e->resolvedType.prim == PrimitiveKind::Double);
leftIsString = e->resolvedType.isString();
}
if (auto* e = dynamic_cast<ExpressionNode*>(rightNode)) {
rightIsFloat = e->resolvedType.isPrimitive() &&
(e->resolvedType.prim == PrimitiveKind::Float ||
e->resolvedType.prim == PrimitiveKind::Double);
rightIsString = e->resolvedType.isString();
}
// String birleştirme (ADR-024): + → STRING_CONCAT
if ((leftIsString || rightIsString) && opcode == Opcode::ADD) {
emitBinaryOp(Opcode::STRING_CONCAT, destSlot, leftSlot, rightSlot);
return destSlot;
}
if (leftIsFloat || rightIsFloat) {
// Int operandı float'a çevir
if (!leftIsFloat) {
int conv = freshSlot();
emitIntToFloat(conv, leftSlot);
leftSlot = conv;
}
if (!rightIsFloat) {
int conv = freshSlot();
emitIntToFloat(conv, rightSlot);
rightSlot = conv;
}
// Float opcode eşleştirmesi
Opcode floatOp = opcode;
if (opcode == Opcode::ADD) floatOp = Opcode::FADD;
else if (opcode == Opcode::SUB) floatOp = Opcode::FSUB;
else if (opcode == Opcode::MUL) floatOp = Opcode::FMUL;
else if (opcode == Opcode::DIV) floatOp = Opcode::FDIV;
// karşılaştırma opcodeları aynı kalır (LESS, GREATER, vb.)
emitBinaryOp(floatOp, destSlot, leftSlot, rightSlot);
} else {
emitBinaryOp(opcode, destSlot, leftSlot, rightSlot);
}
return destSlot; return destSlot;
} }
@ -531,6 +823,111 @@ void IRGenerator::emitLoadSlot(int destSlot, int srcSlot) {
currentFunction_->instructions.push_back(std::move(ins)); currentFunction_->instructions.push_back(std::move(ins));
} }
void IRGenerator::emitLoadGlobal(int destSlot, int globalIndex) {
Instruction ins(Opcode::LOAD_GLOBAL);
ins.dest = destSlot;
ins.intValue = globalIndex;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitStoreGlobal(int srcSlot, int globalIndex) {
Instruction ins(Opcode::STORE_GLOBAL);
ins.src = srcSlot;
ins.intValue = globalIndex;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitLoadFloat(int destSlot, double value) {
Instruction ins(Opcode::LOAD_FLOAT);
ins.dest = destSlot;
ins.floatValue = value;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitIntToFloat(int destSlot, int srcSlot) {
Instruction ins(Opcode::INT_TO_FLOAT);
ins.dest = destSlot;
ins.src = srcSlot;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitStructNew(int destSlot, const std::string& structType, int fieldCount) {
Instruction ins(Opcode::STRUCT_NEW);
ins.dest = destSlot;
ins.intValue = fieldCount;
ins.functionName = structType; // struct tip adı
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitFieldGet(int destSlot, int objSlot, int fieldIdx) {
Instruction ins(Opcode::FIELD_GET);
ins.dest = destSlot;
ins.src = objSlot;
ins.intValue = fieldIdx;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitFieldSet(int objSlot, int fieldIdx, int valSlot) {
Instruction ins(Opcode::FIELD_SET);
ins.dest = objSlot;
ins.intValue = fieldIdx;
ins.right = valSlot;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitArrayNew(int destSlot, int capacity) {
Instruction ins(Opcode::ARRAY_NEW);
ins.dest = destSlot;
ins.intValue = capacity;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitArrayGet(int destSlot, int arrSlot, int idxSlot) {
Instruction ins(Opcode::ARRAY_GET);
ins.dest = destSlot;
ins.left = arrSlot;
ins.right = idxSlot;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitArraySet(int arrSlot, int idxSlot, int valSlot) {
Instruction ins(Opcode::ARRAY_SET);
ins.dest = arrSlot;
ins.left = idxSlot;
ins.right = valSlot;
currentFunction_->instructions.push_back(std::move(ins));
}
void IRGenerator::emitArrayLen(int destSlot, int arrSlot) {
Instruction ins(Opcode::ARRAY_LEN);
ins.dest = destSlot;
ins.src = arrSlot;
currentFunction_->instructions.push_back(std::move(ins));
}
int IRGenerator::getStructFieldIndex(const std::string& structType, const std::string& fieldName) const {
auto it = structLayouts_.find(structType);
if (it == structLayouts_.end()) return -1;
for (int i = 0; i < (int)it->second.size(); i++)
if (it->second[i].first == fieldName) return i;
return -1;
}
int IRGenerator::getStructFieldCount(const std::string& structType) const {
auto it = structLayouts_.find(structType);
if (it == structLayouts_.end()) return 0;
return (int)it->second.size();
}
bool IRGenerator::isGlobal(const std::string& name) const {
return nameToGlobal_.count(name) > 0;
}
int IRGenerator::getGlobalIndex(const std::string& name) const {
auto it = nameToGlobal_.find(name);
return (it != nameToGlobal_.end()) ? it->second : -1;
}
void IRGenerator::emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot) { void IRGenerator::emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot) {
Instruction ins(op); Instruction ins(op);
ins.dest = destSlot; ins.dest = destSlot;
@ -557,7 +954,14 @@ int IRGenerator::emitJumpIfFalse(int condSlot) {
ins.cond = condSlot; ins.cond = condSlot;
ins.jumpTarget = -1; // henüz bilinmiyor — patchJump() bekliyor ins.jumpTarget = -1; // henüz bilinmiyor — patchJump() bekliyor
currentFunction_->instructions.push_back(std::move(ins)); currentFunction_->instructions.push_back(std::move(ins));
// Bu instruction'ın indeksini döndür (backpatch için) return (int)currentFunction_->instructions.size() - 1;
}
int IRGenerator::emitJumpIfTrue(int condSlot) {
Instruction ins(Opcode::JIF_TRUE);
ins.cond = condSlot;
ins.jumpTarget = -1;
currentFunction_->instructions.push_back(std::move(ins));
return (int)currentFunction_->instructions.size() - 1; return (int)currentFunction_->instructions.size() - 1;
} }

View File

@ -22,8 +22,11 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include <utility>
#include "ir/ir_program.hpp" #include "ir/ir_program.hpp"
#include "symbol/symbol_table.hpp" #include "symbol/symbol_table.hpp"
#include "core/type.hpp"
#include "parser/ast_node.hpp" #include "parser/ast_node.hpp"
class IRGenerator { class IRGenerator {
@ -55,7 +58,18 @@ private:
// Talimatları currentFunction_->instructions'a ekler. // Talimatları currentFunction_->instructions'a ekler.
void emitLoadConst(int destSlot, int value); void emitLoadConst(int destSlot, int value);
void emitLoadFloat(int destSlot, double value);
void emitIntToFloat(int destSlot, int srcSlot);
void emitLoadSlot(int destSlot, int srcSlot); void emitLoadSlot(int destSlot, int srcSlot);
void emitLoadGlobal(int destSlot, int globalIndex);
void emitStoreGlobal(int srcSlot, int globalIndex);
void emitStructNew(int destSlot, const std::string& structType, int fieldCount);
void emitFieldGet(int destSlot, int objSlot, int fieldIdx);
void emitFieldSet(int objSlot, int fieldIdx, int valSlot);
void emitArrayNew(int destSlot, int capacity);
void emitArrayGet(int destSlot, int arrSlot, int idxSlot);
void emitArraySet(int arrSlot, int idxSlot, int valSlot);
void emitArrayLen(int destSlot, int arrSlot);
void emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot); void emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot);
void emitReturn(int srcSlot); void emitReturn(int srcSlot);
// Koşulsuz atlama yazar; instruction indeksini döndürür (backpatch için). // Koşulsuz atlama yazar; instruction indeksini döndürür (backpatch için).
@ -66,19 +80,44 @@ private:
// Döndürülen indeks ileride patchJump() ile doldurulur (backpatch). // Döndürülen indeks ileride patchJump() ile doldurulur (backpatch).
int emitJumpIfFalse(int condSlot); int emitJumpIfFalse(int condSlot);
// JIF_TRUE talimatını -1 hedefle yazar, instruction indeksini döndürür.
int emitJumpIfTrue(int condSlot);
// Daha önce -1 hedefle yazılan jump'ın hedefini şu anki pozisyona doldur. // Daha önce -1 hedefle yazılan jump'ın hedefini şu anki pozisyona doldur.
void patchJump(int instrIndex); void patchJump(int instrIndex);
// Şu an kaç talimat üretildi? (jump hedefi belirlemek için) // Şu an kaç talimat üretildi? (jump hedefi belirlemek için)
int currentInstrIndex() const; int currentInstrIndex() const;
// ── Döngü bağlamı yığını — break/continue hedefleri ─────────────────
// Her döngüye girerken bir giriş push'lanır, çıkınca pop'lanır.
// İç içe döngülerde en üstteki giriş en içteki döngüye aittir.
struct LoopContext {
std::vector<int> breakJumps; // patch bekleyen break JMP indeksleri
std::vector<int> continueJumps; // patch bekleyen continue JMP indeksleri
};
std::vector<LoopContext> loopContextStack_;
// ── Per-function üretim durumu ──────────────────────────────────────── // ── Per-function üretim durumu ────────────────────────────────────────
IRFunction* currentFunction_ = nullptr; // şu an üretilen fonksiyon IRFunction* currentFunction_ = nullptr; // şu an üretilen fonksiyon
int nextSlot_ = 0; // sıradaki boş slot numarası int nextSlot_ = 0; // sıradaki boş slot numarası
// Değişken ismi → slot numarası. // Değişken ismi → slot numarası (lokal).
// Sınırlama: aynı isimdeki farklı scope değişkenleri çakışır (TODO).
std::unordered_map<std::string, int> nameToSlot_; std::unordered_map<std::string, int> nameToSlot_;
// Global değişken ismi → global index
std::unordered_map<std::string, int> nameToGlobal_;
int globalCount_ = 0;
// Struct alan düzeni: struct adı → sıralı [(alan adı, Type)] listesi
// Sembol tablosundan generate() başında kopyalanır.
std::unordered_map<std::string, std::vector<std::pair<std::string, Type>>> structLayouts_;
int getStructFieldIndex(const std::string& structType, const std::string& fieldName) const;
int getStructFieldCount(const std::string& structType) const;
bool isGlobal(const std::string& name) const;
int getGlobalIndex(const std::string& name) const;
}; };
#endif // SAQUT_IR_GENERATOR #endif // SAQUT_IR_GENERATOR

View File

@ -3,6 +3,14 @@
void IRProgram::dump() const { void IRProgram::dump() const {
std::cout << "IR DUMP\n\n"; std::cout << "IR DUMP\n\n";
if (globalCount > 0) {
std::cout << "GLOBALS (" << globalCount << ")\n";
for (int i = 0; i < (int)globalNames.size(); i++)
std::cout << " global[" << i << "] = " << globalNames[i] << "\n";
std::cout << "\n";
}
for (const auto& name : functionOrder) { for (const auto& name : functionOrder) {
auto it = functions.find(name); auto it = functions.find(name);
if (it != functions.end()) it->second.dump(); if (it != functions.end()) it->second.dump();

View File

@ -29,6 +29,14 @@ struct IRProgram {
// Ekleme sırası (dump'ta orijinal sırayla göstermek için) // Ekleme sırası (dump'ta orijinal sırayla göstermek için)
std::vector<std::string> functionOrder; std::vector<std::string> functionOrder;
// Modül-düzeyi değişkenler (LOAD_GLOBAL / STORE_GLOBAL için)
// Bunlar "global" değil — bu IRProgram'ın temsil ettiği tek modüle aittir.
// Çok-modüllü derlemede her modülün kendi IRProgram'ı (veya ayrı slot alanı) olur.
// TODO(#modül-scope): moduleId alanı eklenince Interpreter bu alana
// frame.function->moduleId üzerinden erişecek (bkz. TODO.md).
int globalCount = 0;
std::vector<std::string> globalNames; // index → isim (dump için)
// Yeni fonksiyon ekle // Yeni fonksiyon ekle
void addFunction(IRFunction fn) { void addFunction(IRFunction fn) {
functionOrder.push_back(fn.name); functionOrder.push_back(fn.name);

View File

@ -104,6 +104,10 @@ private:
case TokenType::GREATER: case TokenType::GREATER:
case TokenType::LESS_EQUAL: case TokenType::LESS_EQUAL:
case TokenType::GREATER_EQUAL: case TokenType::GREATER_EQUAL:
case TokenType::AMPERSAND:
case TokenType::PIPE:
case TokenType::LSHIFT:
case TokenType::RSHIFT:
case TokenType::AMPERSAND_AMPERSAND: case TokenType::AMPERSAND_AMPERSAND:
case TokenType::PIPE_PIPE: case TokenType::PIPE_PIPE:
return true; return true;
@ -125,6 +129,10 @@ private:
case TokenType::GREATER: return l > r ? 1 : 0; case TokenType::GREATER: return l > r ? 1 : 0;
case TokenType::LESS_EQUAL: return l <= r ? 1 : 0; case TokenType::LESS_EQUAL: return l <= r ? 1 : 0;
case TokenType::GREATER_EQUAL: return l >= r ? 1 : 0; case TokenType::GREATER_EQUAL: return l >= r ? 1 : 0;
case TokenType::AMPERSAND: return l & r;
case TokenType::PIPE: return l | r;
case TokenType::LSHIFT: return l << r;
case TokenType::RSHIFT: return l >> r;
case TokenType::AMPERSAND_AMPERSAND: return (l && r) ? 1 : 0; case TokenType::AMPERSAND_AMPERSAND: return (l && r) ? 1 : 0;
case TokenType::PIPE_PIPE: return (l || r) ? 1 : 0; case TokenType::PIPE_PIPE: return (l || r) ? 1 : 0;
default: return 0; default: return 0;

View File

@ -15,9 +15,12 @@
#include "parser/nodes/declarations.hpp" #include "parser/nodes/declarations.hpp"
#include "parser/nodes/expressions.hpp" #include "parser/nodes/expressions.hpp"
#include "parser/nodes/program.hpp" #include "parser/nodes/program.hpp"
#include "diagnostic/diagnostic_engine.hpp"
class DeadCodeElimPass : public OptimizationPass { class DeadCodeElimPass : public OptimizationPass {
public: public:
explicit DeadCodeElimPass(DiagnosticEngine& diag) : diag_(diag) {}
bool run(ASTNode* root, SymbolTable*) override { bool run(ASTNode* root, SymbolTable*) override {
changed_ = false; changed_ = false;
visit(root); visit(root);
@ -30,6 +33,7 @@ public:
} }
private: private:
DiagnosticEngine& diag_;
bool changed_ = false; bool changed_ = false;
void visit(ASTNode* node) { void visit(ASTNode* node) {
@ -45,11 +49,12 @@ private:
for (auto* child : ch) { for (auto* child : ch) {
if (term) { if (term) {
// Bu deyim erişilemez
if (auto* sn = dynamic_cast<StatementNode*>(child)) { if (auto* sn = dynamic_cast<StatementNode*>(child)) {
if (sn->isReachable) { if (sn->isReachable) {
sn->isReachable = false; sn->isReachable = false;
changed_ = true; changed_ = true;
diag_.report("W003", sn->loc,
"Bu kod hiçbir zaman çalışmaz (return/break/continue sonrası)");
} }
} }
} }
@ -59,12 +64,14 @@ private:
term = true; term = true;
} }
// Erişilemez çocukları sil ve vektörden çıkar // remove_if erişilemez düğümleri sona taşır (silmez), sonra delete
ch.erase(std::remove_if(ch.begin(), ch.end(), auto toErase = std::remove_if(ch.begin(), ch.end(),
[](ASTNode* n) { [](ASTNode* n) {
auto* sn = dynamic_cast<StatementNode*>(n); auto* sn = dynamic_cast<StatementNode*>(n);
return sn && !sn->isReachable; return sn && !sn->isReachable;
}), ch.end()); });
for (auto it = toErase; it != ch.end(); ++it) delete *it;
ch.erase(toErase, ch.end());
// Alt bloklara da in // Alt bloklara da in
for (auto* child : ch) visit(child); for (auto* child : ch) visit(child);

View File

@ -1,9 +1,18 @@
// ============================================================================ // ============================================================================
// saQut — Optimizasyon Yöneticisi (ADR-007, ADR-009) // saQut — Optimizasyon Yöneticisi (ADR-007, ADR-009)
// //
// 1. AST'yi klonlar (orijinal dokunulmaz). // İKİ KULLANIM YOLU:
// 2. Etkin pass'leri fixpoint döngüsüyle çalıştırır. //
// 3. Optimize edilmiş klon sahipliğini döndürür (caller delete eder). // 1. runPassesInPlace(root, table)
// Pass'leri verilen AST üstünde doğrudan çalıştırır — klon yok.
// run / ir / transpile gibi "tek seferlik" komutlar bu yolu kullanır:
// AST'nin tek versiyonu gerekiyor, orijinali saklamaya gerek yok.
//
// 2. optimize(root, table) [sadece ast komutu için]
// Önce deepClone, sonra runPassesInPlace. Orijinali dokunulmaz bırakır.
// Çıktı: optimize edilmiş klon (caller delete eder).
// ast komutunun "öncesi / sonrası" karşılaştırması için zorunlu.
// Diğer komutlar bu yolu ÇAĞIRMAMALI — gereksiz klon maliyeti.
// //
// Fixpoint garantisi: her pass yalnızca küçülten dönüşümler yapar // Fixpoint garantisi: her pass yalnızca küçülten dönüşümler yapar
// (katlama: n düğüm → 1 düğüm; DCE: düğüm siler). Büyüten pass // (katlama: n düğüm → 1 düğüm; DCE: düğüm siler). Büyüten pass
@ -29,22 +38,27 @@ public:
if (cfg.optConstantFolding) if (cfg.optConstantFolding)
passes_.push_back(std::make_unique<ConstantFoldingPass>(diag)); passes_.push_back(std::make_unique<ConstantFoldingPass>(diag));
if (cfg.optDeadCodeElim) if (cfg.optDeadCodeElim)
passes_.push_back(std::make_unique<DeadCodeElimPass>()); passes_.push_back(std::make_unique<DeadCodeElimPass>(diag));
maxRounds_ = cfg.maxFixpointRounds; maxRounds_ = cfg.maxFixpointRounds;
} }
// optimize: AST'yi klonlar ve optimize edilmiş kopyayı döndürür. // Pass'leri verilen AST üstünde yerinde çalıştırır — klon yok.
// Dönen pointer caller'a aittir (delete edilmeli). // run / ir ve diğer tek-versiyon komutları bu yolu kullanır.
ASTNode* optimize(ASTNode* root, SymbolTable* table) { void runPassesInPlace(ASTNode* root, SymbolTable* table) {
ASTNode* clone = deepClone(root);
for (int round = 0; round < maxRounds_; ++round) { for (int round = 0; round < maxRounds_; ++round) {
bool anyChange = false; bool anyChange = false;
for (auto& pass : passes_) for (auto& pass : passes_)
if (pass->run(clone, table)) anyChange = true; if (pass->run(root, table)) anyChange = true;
if (!anyChange) break; if (!anyChange) break;
} }
}
// Önce deepClone, sonra runPassesInPlace. Orijinal dokunulmaz.
// SADECE ast komutu kullanır — öncesi/sonrası karşılaştırması için.
// Dönen pointer caller'a aittir (delete edilmeli).
ASTNode* optimize(ASTNode* root, SymbolTable* table) {
ASTNode* clone = deepClone(root);
runPassesInPlace(clone, table);
return clone; return clone;
} }

View File

@ -87,6 +87,8 @@ enum class ASTKind {
ExpressionStatement, // ifade + noktalı virgül (;) ExpressionStatement, // ifade + noktalı virgül (;)
// children: [expression] // children: [expression]
// Örn: x = 5; veya foo(); // Örn: x = 5; veya foo();
TryStatement, // try { body } catch (Error e) { handler } (ADR-025)
ThrowStatement, // throw <ifade>; (ADR-025)
/* ====== İfadeler (Expressions) ====== */ /* ====== İfadeler (Expressions) ====== */
BinaryExpression, // İkili işlem: sol OP sağ. BinaryExpression, // İkili işlem: sol OP sağ.
@ -107,6 +109,8 @@ enum class ASTKind {
// children: [object], [member] // children: [object], [member]
IndexExpression, // Dizi/indeks erişimi: a[i]. IndexExpression, // Dizi/indeks erişimi: a[i].
// children: [object], [index] // children: [object], [index]
ArrayLiteral, // Dizi literali: [1, 2, 3].
// children: [element0, element1, ...]
}; };
// ============================================================================ // ============================================================================
@ -236,10 +240,12 @@ public:
// KARMAŞIKLIK: O(1) — referans döndürür // KARMAŞIKLIK: O(1) — referans döndürür
std::vector<ASTNode*>& getChildren() { return children; } std::vector<ASTNode*>& getChildren() { return children; }
// ~ASTNode() — Sanal yıkıcı (polimorfik silme için) // ~ASTNode() — children vektörünü özyinelemeli siler.
// delete ASTNode* yapıldığında doğru alt sınıf yıkıcısı çağrılır. // Typed pointer'lar (condition, thenBranch vb.) alt sınıf yıkıcılarına bırakılır;
// Bu olmazsa türetilmiş sınıfların kaynakları sızdırılır. // children vektörü ile typed pointer'lar örtüşmediği için double-delete olmaz.
virtual ~ASTNode() = default; virtual ~ASTNode() {
for (auto* ch : children) delete ch;
}
protected: protected:
// children — Alt düğümlerin vektörü. // children — Alt düğümlerin vektörü.

View File

@ -10,6 +10,7 @@ public:
ASTNode* Right = nullptr; ASTNode* Right = nullptr;
BinaryExpressionNode(); BinaryExpressionNode();
~BinaryExpressionNode() override { delete Left; delete Right; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };

View File

@ -3,6 +3,7 @@
// FunctionDeclNode // FunctionDeclNode
FunctionDeclNode::FunctionDeclNode() { kind = ASTKind::FunctionDecl; } FunctionDeclNode::FunctionDeclNode() { kind = ASTKind::FunctionDecl; }
FunctionDeclNode::~FunctionDeclNode() { for (auto* p : params) delete p; }
void FunctionDeclNode::log(int indent) { void FunctionDeclNode::log(int indent) {
std::cout << jsonIndent(indent) << "FunctionDecl (" << name << " : " << returnType << ")\n"; std::cout << jsonIndent(indent) << "FunctionDecl (" << name << " : " << returnType << ")\n";
for (auto* child : children) child->log(indent + 1); for (auto* child : children) child->log(indent + 1);

View File

@ -11,6 +11,7 @@ public:
std::string returnType; std::string returnType;
std::vector<VariableDeclNode*> params; // TODO(faz2): parametreler std::vector<VariableDeclNode*> params; // TODO(faz2): parametreler
FunctionDeclNode(); FunctionDeclNode();
~FunctionDeclNode() override;
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -21,6 +22,7 @@ public:
std::string name; std::string name;
ASTNode* initExpr = nullptr; ASTNode* initExpr = nullptr;
VariableDeclNode(); VariableDeclNode();
~VariableDeclNode() override { delete initExpr; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };

View File

@ -53,6 +53,23 @@ std::string MemberAccessNode::toJson(int depth) {
return obj.str(); return obj.str();
} }
// ArrayLiteralNode
ArrayLiteralNode::ArrayLiteralNode() { kind = ASTKind::ArrayLiteral; }
void ArrayLiteralNode::log(int indent) {
std::cout << jsonIndent(indent) << "ArrayLiteral [" << elements.size() << " eleman]\n";
for (auto* e : elements) e->log(indent + 1);
}
std::string ArrayLiteralNode::toJson(int depth) {
JsonObject obj(depth);
obj.add("kind", "ArrayLiteral");
obj.addArray("elements", [&]() {
for (auto* e : elements) obj.addItem(e->toJson(depth + 2));
});
obj.addRaw("resolvedType", resolvedTypeJson());
obj.addRaw("location", loc.toJson());
return obj.str();
}
// IndexExpressionNode // IndexExpressionNode
IndexExpressionNode::IndexExpressionNode() { kind = ASTKind::IndexExpression; } IndexExpressionNode::IndexExpressionNode() { kind = ASTKind::IndexExpression; }
void IndexExpressionNode::log(int indent) { void IndexExpressionNode::log(int indent) {

View File

@ -8,6 +8,7 @@ public:
ASTNode* operand = nullptr; ASTNode* operand = nullptr;
TokenType Operator; TokenType Operator;
PostfixNode(); PostfixNode();
~PostfixNode() override { delete operand; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -17,6 +18,7 @@ public:
ASTNode* callee = nullptr; ASTNode* callee = nullptr;
std::vector<ASTNode*> arguments; std::vector<ASTNode*> arguments;
CallExpressionNode(); CallExpressionNode();
~CallExpressionNode() override { delete callee; for (auto* a : arguments) delete a; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -27,6 +29,7 @@ public:
std::string member; std::string member;
bool arrow = false; bool arrow = false;
MemberAccessNode(); MemberAccessNode();
~MemberAccessNode() override { delete object; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -36,6 +39,16 @@ public:
ASTNode* object = nullptr; ASTNode* object = nullptr;
ASTNode* index = nullptr; ASTNode* index = nullptr;
IndexExpressionNode(); IndexExpressionNode();
~IndexExpressionNode() override { delete object; delete index; }
void log(int indent = 0) override;
std::string toJson(int depth = 0) override;
};
class ArrayLiteralNode : public ExpressionNode {
public:
std::vector<ASTNode*> elements;
ArrayLiteralNode();
~ArrayLiteralNode() override { for (auto* e : elements) delete e; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };

View File

@ -1,6 +1,5 @@
#include "parser/nodes/identifier.hpp" #include "parser/nodes/identifier.hpp"
#include <iostream> #include <iostream>
#include <sstream>
#include "parser/ast_json.hpp" #include "parser/ast_json.hpp"
IdentifierNode::IdentifierNode() { kind = ASTKind::Identifier; } IdentifierNode::IdentifierNode() { kind = ASTKind::Identifier; }
@ -11,14 +10,10 @@ void IdentifierNode::log(int indent) {
} }
std::string IdentifierNode::toJson(int depth) { std::string IdentifierNode::toJson(int depth) {
std::string in = jsonIndent(depth); JsonObject obj(depth);
std::string name = parserToken.token ? parserToken.token->token : "?"; obj.add("kind", "Identifier");
std::ostringstream ss; obj.add("name", parserToken.token ? parserToken.token->token : "?");
ss << "{\n" obj.addRaw("resolvedType", resolvedTypeJson());
<< in << " \"kind\": \"Identifier\",\n" obj.addRaw("location", loc.toJson());
<< in << " \"name\": \"" << jsonEscape(name) << "\",\n" return obj.str();
<< in << " \"resolvedType\": " << resolvedTypeJson() << ",\n"
<< in << " \"location\": " << loc.toJson() << "\n"
<< in << "}";
return ss.str();
} }

View File

@ -1,6 +1,5 @@
#include "parser/nodes/literal.hpp" #include "parser/nodes/literal.hpp"
#include <iostream> #include <iostream>
#include <sstream>
#include "parser/ast_json.hpp" #include "parser/ast_json.hpp"
LiteralNode::LiteralNode() { kind = ASTKind::Literal; } LiteralNode::LiteralNode() { kind = ASTKind::Literal; }
@ -18,22 +17,17 @@ void LiteralNode::log(int indent) {
} }
std::string LiteralNode::toJson(int depth) { std::string LiteralNode::toJson(int depth) {
std::string in = jsonIndent(depth);
std::string val = hasDirectValue ? std::to_string(directIntValue) std::string val = hasDirectValue ? std::to_string(directIntValue)
: (parserToken.token ? parserToken.token->token : "?"); : (parserToken.token ? parserToken.token->token : "?");
std::ostringstream ss; JsonObject obj(depth);
ss << "{\n" obj.add("kind", "Literal");
<< in << " \"kind\": \"Literal\",\n" obj.add("literalType", literalTypeToString(literalType));
<< in << " \"literalType\": \"" << literalTypeToString(literalType) << "\",\n" obj.add("value", val);
<< in << " \"value\": \"" << jsonEscape(val) << "\""; if (literalType == LiteralType::INTEGER && literalBase != 10)
if (literalType == LiteralType::INTEGER && literalBase != 10) { obj.add("base", literalBase);
ss << ",\n" << in << " \"base\": " << literalBase; if (literalType == LiteralType::FLOAT)
} obj.add("isFloat", true);
if (literalType == LiteralType::FLOAT) { obj.addRaw("resolvedType", resolvedTypeJson());
ss << ",\n" << in << " \"isFloat\": true"; obj.addRaw("location", loc.toJson());
} return obj.str();
ss << ",\n" << in << " \"resolvedType\": " << resolvedTypeJson();
ss << ",\n" << in << " \"location\": " << loc.toJson() << "\n"
<< in << "}";
return ss.str();
} }

View File

@ -147,3 +147,36 @@ std::string ExpressionStatementNode::toJson(int depth) {
obj.addRaw("location", loc.toJson()); obj.addRaw("location", loc.toJson());
return obj.str(); return obj.str();
} }
// TryStatementNode (ADR-025)
TryStatementNode::TryStatementNode() { kind = ASTKind::TryStatement; }
void TryStatementNode::log(int indent) {
std::cout << jsonIndent(indent) << "TryStatement (catch " << catchVar << ")\n";
if (body) body->log(indent + 1);
if (handler) handler->log(indent + 1);
}
std::string TryStatementNode::toJson(int depth) {
JsonObject obj(depth);
obj.add("kind", "TryStatement");
obj.add("catchVar", catchVar);
if (body) obj.addRaw("body", body->toJson(depth + 1));
if (handler) obj.addRaw("handler", handler->toJson(depth + 1));
obj.add("isReachable", isReachable);
obj.addRaw("location", loc.toJson());
return obj.str();
}
// ThrowStatementNode (ADR-025)
ThrowStatementNode::ThrowStatementNode() { kind = ASTKind::ThrowStatement; }
void ThrowStatementNode::log(int indent) {
std::cout << jsonIndent(indent) << "ThrowStatement\n";
if (value) value->log(indent + 1);
}
std::string ThrowStatementNode::toJson(int depth) {
JsonObject obj(depth);
obj.add("kind", "ThrowStatement");
if (value) obj.addRaw("value", value->toJson(depth + 1));
obj.add("isReachable", isReachable);
obj.addRaw("location", loc.toJson());
return obj.str();
}

View File

@ -16,6 +16,7 @@ public:
ASTNode* thenBranch = nullptr; ASTNode* thenBranch = nullptr;
ASTNode* elseBranch = nullptr; ASTNode* elseBranch = nullptr;
IfStatementNode(); IfStatementNode();
~IfStatementNode() override { delete condition; delete thenBranch; delete elseBranch; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -25,6 +26,7 @@ public:
ASTNode* condition = nullptr; ASTNode* condition = nullptr;
ASTNode* body = nullptr; ASTNode* body = nullptr;
WhileStatementNode(); WhileStatementNode();
~WhileStatementNode() override { delete condition; delete body; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -36,6 +38,7 @@ public:
ASTNode* update = nullptr; ASTNode* update = nullptr;
ASTNode* body = nullptr; ASTNode* body = nullptr;
ForStatementNode(); ForStatementNode();
~ForStatementNode() override { delete init; delete condition; delete update; delete body; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -45,6 +48,7 @@ public:
ASTNode* condition = nullptr; ASTNode* condition = nullptr;
ASTNode* body = nullptr; ASTNode* body = nullptr;
DoWhileStatementNode(); DoWhileStatementNode();
~DoWhileStatementNode() override { delete body; delete condition; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -53,6 +57,7 @@ class ReturnStatementNode : public StatementNode {
public: public:
ASTNode* value = nullptr; ASTNode* value = nullptr;
ReturnStatementNode(); ReturnStatementNode();
~ReturnStatementNode() override { delete value; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };
@ -75,6 +80,29 @@ class ExpressionStatementNode : public StatementNode {
public: public:
ASTNode* expression = nullptr; ASTNode* expression = nullptr;
ExpressionStatementNode(); ExpressionStatementNode();
~ExpressionStatementNode() override { delete expression; }
void log(int indent = 0) override;
std::string toJson(int depth = 0) override;
};
// ADR-025: try { body } catch (Error catchVar) { handler }
class TryStatementNode : public StatementNode {
public:
ASTNode* body = nullptr;
std::string catchVar; // catch değişken adı (ör. "e")
ASTNode* handler = nullptr;
TryStatementNode();
~TryStatementNode() override { delete body; delete handler; }
void log(int indent = 0) override;
std::string toJson(int depth = 0) override;
};
// ADR-025: throw <ifade>;
class ThrowStatementNode : public StatementNode {
public:
ASTNode* value = nullptr;
ThrowStatementNode();
~ThrowStatementNode() override { delete value; }
void log(int indent = 0) override; void log(int indent = 0) override;
std::string toJson(int depth = 0) override; std::string toJson(int depth = 0) override;
}; };

View File

@ -85,8 +85,15 @@ ASTNode* Parser::parseDeclaration() {
})) { })) {
auto la1 = lookahead(1); auto la1 = lookahead(1);
auto la2 = lookahead(2); auto la2 = lookahead(2);
// int name( → fonksiyon
if (la1.type == TokenType::IDENTIFIER && la2.type == TokenType::LPAREN) if (la1.type == TokenType::IDENTIFIER && la2.type == TokenType::LPAREN)
return parseFunctionDecl(); return parseFunctionDecl();
// int? name( → nullable dönüş tipli fonksiyon (ADR-021)
if (la1.type == TokenType::TERNARY) {
auto la3 = lookahead(3);
if (la2.type == TokenType::IDENTIFIER && la3.type == TokenType::LPAREN)
return parseFunctionDecl();
}
return parseVariableDecl(); return parseVariableDecl();
} }
@ -99,6 +106,11 @@ ASTNode* Parser::parseDeclaration() {
auto la2 = lookahead(2); auto la2 = lookahead(2);
if (la1.type == TokenType::IDENTIFIER && la2.type == TokenType::LPAREN) if (la1.type == TokenType::IDENTIFIER && la2.type == TokenType::LPAREN)
return parseFunctionDecl(); return parseFunctionDecl();
if (la1.type == TokenType::TERNARY) {
auto la3 = lookahead(3);
if (la2.type == TokenType::IDENTIFIER && la3.type == TokenType::LPAREN)
return parseFunctionDecl();
}
if (la1.type == TokenType::IDENTIFIER) if (la1.type == TokenType::IDENTIFIER)
return parseVariableDecl(); return parseVariableDecl();
} }
@ -150,6 +162,23 @@ ASTNode* Parser::parseNullDenotation() {
return expr; return expr;
} }
// Array literal: [expr, expr, ...]
if (ct.type == TokenType::LBRACKET) {
nextToken();
ArrayLiteralNode* arr = new ArrayLiteralNode();
arr->loc = ct.token ? ct.token->loc : SourceLocation{};
if (currentToken().type != TokenType::RBRACKET) {
arr->elements.push_back(parseExpression(0));
while (currentToken().type == TokenType::COMMA) {
nextToken();
arr->elements.push_back(parseExpression(0));
}
}
if (currentToken().type == TokenType::RBRACKET)
nextToken();
return arr;
}
if (ct.is({ if (ct.is({
TokenType::PLUS_PLUS, TokenType::MINUS_MINUS, TokenType::PLUS_PLUS, TokenType::MINUS_MINUS,
TokenType::PLUS, TokenType::MINUS, TokenType::PLUS, TokenType::MINUS,
@ -299,6 +328,10 @@ ASTNode* Parser::parseFunctionDecl() {
fn->returnType = currentToken().token->token; fn->returnType = currentToken().token->token;
nextToken(); nextToken();
// ADR-021: nullable dönüş tipi — int? f()
if (currentToken().type == TokenType::TERNARY)
{ nextToken(); fn->returnType += "?"; }
fn->name = currentToken().token->token; fn->name = currentToken().token->token;
nextToken(); nextToken();
@ -315,6 +348,16 @@ ASTNode* Parser::parseFunctionDecl() {
if (!isTypeKw || !typeTok.token) break; if (!isTypeKw || !typeTok.token) break;
std::string paramType = typeTok.token->token; std::string paramType = typeTok.token->token;
nextToken(); nextToken();
// int[] a — tip sonrasında [] varsa array tipi
if (currentToken().type == TokenType::LBRACKET) {
nextToken();
if (currentToken().type == TokenType::RBRACKET)
nextToken();
paramType += "[]";
}
// ADR-021: nullable parametre — int? a
if (currentToken().type == TokenType::TERNARY)
{ nextToken(); paramType += "?"; }
if (currentToken().type != TokenType::IDENTIFIER || !currentToken().token) break; if (currentToken().type != TokenType::IDENTIFIER || !currentToken().token) break;
VariableDeclNode* param = new VariableDeclNode(); VariableDeclNode* param = new VariableDeclNode();
param->loc = currentToken().token->loc; param->loc = currentToken().token->loc;
@ -364,6 +407,18 @@ ASTNode* Parser::parseVariableDecl() {
vd->varType = currentToken().token->token; vd->varType = currentToken().token->token;
nextToken(); nextToken();
// Java/C# stili: int[] x — tip adından hemen sonra [] gelir
if (currentToken().type == TokenType::LBRACKET) {
nextToken();
if (currentToken().type == TokenType::RBRACKET)
nextToken();
vd->varType += "[]";
}
// ADR-021: nullable soneki — int? x
if (currentToken().type == TokenType::TERNARY)
{ nextToken(); vd->varType += "?"; }
if (currentToken().type != TokenType::IDENTIFIER) { if (currentToken().type != TokenType::IDENTIFIER) {
std::cerr << "Parser hatası: değişken ismi bekleniyor\n"; std::cerr << "Parser hatası: değişken ismi bekleniyor\n";
return vd; return vd;
@ -372,6 +427,7 @@ ASTNode* Parser::parseVariableDecl() {
vd->name = currentToken().token->token; vd->name = currentToken().token->token;
nextToken(); nextToken();
// C stili: int x[] — geriye dönük uyumluluk (postfix [])
if (currentToken().type == TokenType::LBRACKET) { if (currentToken().type == TokenType::LBRACKET) {
nextToken(); nextToken();
while (currentToken().type != TokenType::RBRACKET && while (currentToken().type != TokenType::RBRACKET &&
@ -380,6 +436,7 @@ ASTNode* Parser::parseVariableDecl() {
nextToken(); nextToken();
if (currentToken().type == TokenType::RBRACKET) if (currentToken().type == TokenType::RBRACKET)
nextToken(); nextToken();
if (vd->varType.back() != ']') vd->varType += "[]";
} }
if (currentToken().type == TokenType::EQUAL) { if (currentToken().type == TokenType::EQUAL) {
@ -452,6 +509,12 @@ ASTNode* Parser::parseStatement() {
if (ct.type == TokenType::KW_CONTINUE) if (ct.type == TokenType::KW_CONTINUE)
return parseContinueStatement(); return parseContinueStatement();
if (ct.type == TokenType::KW_TRY)
return parseTryStatement();
if (ct.type == TokenType::KW_THROW)
return parseThrowStatement();
if (ct.is({ if (ct.is({
TokenType::KW_VOID, TokenType::KW_INT, TokenType::KW_FLOAT_TYPE, TokenType::KW_VOID, TokenType::KW_INT, TokenType::KW_FLOAT_TYPE,
TokenType::KW_DOUBLE, TokenType::KW_BOOL, TokenType::KW_CHAR, TokenType::KW_DOUBLE, TokenType::KW_BOOL, TokenType::KW_CHAR,
@ -463,6 +526,15 @@ ASTNode* Parser::parseStatement() {
if (ct.type == TokenType::KW_STRUCT) if (ct.type == TokenType::KW_STRUCT)
return parseStructDecl(); return parseStructDecl();
// Kullanıcı tanımlı struct tipiyle değişken bildirimi: Point p; veya Point p = ...;
if (ct.type == TokenType::IDENTIFIER) {
auto la1 = lookahead(1);
// "TypeName varName" veya "TypeName varName = ..." → değişken bildirimi
// (TypeName LPAREN → ifade; o durumda parseExpressionStatement devam eder)
if (la1.type == TokenType::IDENTIFIER)
return parseVariableDecl();
}
return parseExpressionStatement(); return parseExpressionStatement();
} }
@ -627,3 +699,43 @@ ASTNode* Parser::parseExpressionStatement() {
return es; return es;
} }
// ADR-025: try { body } catch (Error catchVar) { handler }
ASTNode* Parser::parseTryStatement() {
TryStatementNode* ts = new TryStatementNode();
ts->loc = currentToken().token->loc;
nextToken(); // tüket: try
ts->body = parseBlock();
// catch (Error e)
if (currentToken().type == TokenType::KW_CATCH) {
nextToken(); // tüket: catch
if (currentToken().type == TokenType::LPAREN)
nextToken(); // tüket: (
// "Error" tip adını atla
if (currentToken().type == TokenType::IDENTIFIER ||
currentToken().type == TokenType::KW_STRING_TYPE)
nextToken(); // tüket: Error (ya da herhangi bir tip adı)
// catch değişken adını al
if (currentToken().type == TokenType::IDENTIFIER && currentToken().token)
ts->catchVar = currentToken().token->token;
nextToken(); // tüket: değişken adı
if (currentToken().type == TokenType::RPAREN)
nextToken(); // tüket: )
ts->handler = parseBlock();
}
return ts;
}
// ADR-025: throw <ifade>;
ASTNode* Parser::parseThrowStatement() {
ThrowStatementNode* th = new ThrowStatementNode();
th->loc = currentToken().token->loc;
nextToken(); // tüket: throw
th->value = parseExpression();
if (currentToken().type == TokenType::SEMICOLON)
nextToken();
return th;
}

View File

@ -51,6 +51,8 @@ private:
ASTNode* parseBreakStatement(); ASTNode* parseBreakStatement();
ASTNode* parseContinueStatement(); ASTNode* parseContinueStatement();
ASTNode* parseExpressionStatement(); ASTNode* parseExpressionStatement();
ASTNode* parseTryStatement();
ASTNode* parseThrowStatement();
// --- İfadeler (Pratt parser) --- // --- İfadeler (Pratt parser) ---
ASTNode* parseExpression(); ASTNode* parseExpression();

View File

@ -21,6 +21,50 @@ int TypeChecker::numericRank(const Type& t) {
} }
} }
// ADR-021: "a != null" / "a == null" kalıbını ayrıştır
// Dönüş: {varName, isNotNull} — varName boşsa kalıp tanınmadı.
std::pair<std::string, bool> TypeChecker::extractNullCheck(ASTNode* cond) {
if (!cond || cond->kind != ASTKind::BinaryExpression) return {"", false};
auto* bin = (BinaryExpressionNode*)cond;
bool isNE = (bin->Operator == TokenType::BANG_EQUAL);
bool isEE = (bin->Operator == TokenType::EQUAL_EQUAL);
if (!isNE && !isEE) return {"", false};
// Hangi taraf null literal?
auto isNullLit = [](ASTNode* n) -> bool {
if (!n || n->kind != ASTKind::Literal) return false;
return ((LiteralNode*)n)->literalType == LiteralType::BOŞ;
};
auto identName = [](ASTNode* n) -> std::string {
if (!n || n->kind != ASTKind::Identifier) return "";
auto* id = (IdentifierNode*)n;
return id->parserToken.token ? id->parserToken.token->token : "";
};
std::string var;
if (isNullLit(bin->Right)) var = identName(bin->Left);
else if (isNullLit(bin->Left)) var = identName(bin->Right);
if (var.empty()) return {"", false};
return {var, isNE}; // isNE=true → "a != null"; false → "a == null"
}
// ADR-021: guard pattern — bu statement her zaman çıkış yapıyor mu?
bool TypeChecker::alwaysExits(ASTNode* stmt) {
if (!stmt) return false;
switch (stmt->kind) {
case ASTKind::ReturnStatement:
case ASTKind::ThrowStatement:
case ASTKind::BreakStatement:
case ASTKind::ContinueStatement:
return true;
case ASTKind::Block: {
auto& ch = stmt->getChildren();
return !ch.empty() && alwaysExits(ch.back());
}
default: return false;
}
}
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
// check — giriş noktası // check — giriş noktası
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
@ -62,21 +106,41 @@ bool TypeChecker::checkAssign(const Type& target, const Type& src,
const SourceLocation& loc, const SourceLocation& loc,
const std::string& ctx) { const std::string& ctx) {
if (target.isError() || src.isError()) return true; // önceki hata, sessiz geç if (target.isError() || src.isError()) return true; // önceki hata, sessiz geç
if (target.equals(src)) return true;
// ADR-021: null literal ataması
if (src.isNullLiteral()) {
if (target.nullable) return true; // T? ← null → OK
diag_.report("E003", loc,
"'" + ctx + "': null non-null tipine (" + target.toString() + ") atanamaz");
return false;
}
// ADR-021: nullable uyumu
// T? ← T → OK (widening: non-null, nullable'a gider)
// T ← T? → E (narrowing: nullable, non-null'a gidemez; narrowing gerekli)
if (src.nullable && !target.nullable && src.equalsBase(target)) {
diag_.report("E003", loc,
"'" + ctx + "': " + src.toString() +
" nullable tipi non-null " + target.toString() + " tipine atanamaz"
" (if ile null kontrolü yapın)");
return false;
}
// T? ← T → OK (equalsBase eşleşiyorsa, nullable farkı widening)
if (!src.nullable && target.nullable && src.equalsBase(target)) return true;
if (target.equals(src)) return true;
int tRank = numericRank(target); int tRank = numericRank(target);
int sRank = numericRank(src); int sRank = numericRank(src);
if (tRank >= 0 && sRank >= 0) { if (tRank >= 0 && sRank >= 0) {
if (tRank > sRank) { if (tRank > sRank) {
// Genişletme (widening): int→float, int→double, float→double if (srcIsLiteral) return true;
if (srcIsLiteral) return true; // literal bağlama-göre tiplenir, uyarısız
diag_.report("W004", loc, diag_.report("W004", loc,
"'" + ctx + "': " + src.toString() + "'" + ctx + "': " + src.toString() +
"" + target.toString() + " örtük genişletme"); "" + target.toString() + " örtük genişletme");
return true; return true;
} else { } else {
// Daraltma (narrowing): float→int, double→float, vb.
diag_.report("E003", loc, diag_.report("E003", loc,
"'" + ctx + "': " + src.toString() + "'" + ctx + "': " + src.toString() +
"" + target.toString() + " daraltma (veri kaybı)"); "" + target.toString() + " daraltma (veri kaybı)");
@ -84,7 +148,6 @@ bool TypeChecker::checkAssign(const Type& target, const Type& src,
} }
} }
// Tamamen farklı tipler
diag_.report("E003", loc, diag_.report("E003", loc,
"'" + ctx + "': " + src.toString() + "'" + ctx + "': " + src.toString() +
" tipi " + target.toString() + " tipine atanamaz"); " tipi " + target.toString() + " tipine atanamaz");
@ -100,13 +163,32 @@ void TypeChecker::checkStmt(ASTNode* node) {
switch (node->kind) { switch (node->kind) {
case ASTKind::Block: case ASTKind::Block: {
for (ASTNode* child : node->getChildren()) checkStmt(child); // ADR-021: guard/sıralı narrowing — if (a == null) return; → sonrasında a non-null
std::vector<std::string> guardNarrowed; // bu blokta guard'la daraltılanlar
for (ASTNode* child : node->getChildren()) {
checkStmt(child);
// guard kontrolü: if (a == null) { return/throw/break/continue; }
if (child->kind == ASTKind::IfStatement) {
auto* ifn = (IfStatementNode*)child;
if (!ifn->elseBranch && ifn->thenBranch && alwaysExits(ifn->thenBranch)) {
auto [var, isNotNull] = extractNullCheck(ifn->condition);
if (!var.empty() && !isNotNull) { // "a == null" → guard
narrowedNonNull_.insert(var);
guardNarrowed.push_back(var);
}
}
}
}
for (auto& v : guardNarrowed) narrowedNonNull_.erase(v);
break; break;
}
case ASTKind::VariableDecl: { case ASTKind::VariableDecl: {
auto* vd = (VariableDeclNode*)node; auto* vd = (VariableDeclNode*)node;
Type targetType = Type::fromName(vd->varType); Type targetType = Type::fromName(vd->varType);
if (targetType.isError() && table_.structLayouts.count(vd->varType))
targetType = Type::structType(vd->varType);
if (vd->initExpr) { if (vd->initExpr) {
Type srcType = checkExpr(vd->initExpr, targetType); Type srcType = checkExpr(vd->initExpr, targetType);
bool isLit = vd->initExpr->kind == ASTKind::Literal; bool isLit = vd->initExpr->kind == ASTKind::Literal;
@ -142,9 +224,23 @@ void TypeChecker::checkStmt(ASTNode* node) {
case ASTKind::IfStatement: { case ASTKind::IfStatement: {
auto* ifn = (IfStatementNode*)node; auto* ifn = (IfStatementNode*)node;
if (ifn->condition) checkExpr(ifn->condition); if (ifn->condition) checkExpr(ifn->condition);
// ADR-021: nested narrowing — if (a != null) { a non-null } else { a null }
auto [narrowVar, isNotNull] = extractNullCheck(ifn->condition);
if (!narrowVar.empty() && isNotNull) // "a != null" → then'de non-null
narrowedNonNull_.insert(narrowVar);
if (ifn->thenBranch) checkStmt(ifn->thenBranch); if (ifn->thenBranch) checkStmt(ifn->thenBranch);
if (!narrowVar.empty() && isNotNull)
narrowedNonNull_.erase(narrowVar);
if (!narrowVar.empty() && !isNotNull) // "a == null" → else'de non-null
narrowedNonNull_.insert(narrowVar);
if (ifn->elseBranch) checkStmt(ifn->elseBranch); if (ifn->elseBranch) checkStmt(ifn->elseBranch);
if (!narrowVar.empty() && !isNotNull)
narrowedNonNull_.erase(narrowVar);
break; break;
} }
@ -178,6 +274,21 @@ void TypeChecker::checkStmt(ASTNode* node) {
case ASTKind::ContinueStatement: case ASTKind::ContinueStatement:
break; // yapısal doğrulama StructuralValidator'ın işi break; // yapısal doğrulama StructuralValidator'ın işi
// ADR-025: try { body } catch (Error e) { handler }
case ASTKind::TryStatement: {
auto* ts = (TryStatementNode*)node;
if (ts->body) checkStmt(ts->body);
if (ts->handler) checkStmt(ts->handler);
break;
}
// ADR-025: throw <ifade>; — unchecked, herhangi bir değer atılabilir
case ASTKind::ThrowStatement: {
auto* th = (ThrowStatementNode*)node;
if (th->value) checkExpr(th->value);
break;
}
default: default:
break; break;
} }
@ -220,7 +331,14 @@ Type TypeChecker::checkExpr(ASTNode* node, const Type& expected) {
break; break;
case LiteralType::BOOLEAN: result = Type::Bool(); break; case LiteralType::BOOLEAN: result = Type::Bool(); break;
case LiteralType::STRING: result = Type::String(); break; case LiteralType::STRING: result = Type::String(); break;
default: result = Type::error(); break; case LiteralType::BOŞ:
// null literal: bağlam nullable ise o tip, değilse Void+nullable (null sentinel)
if (!expected.isError() && expected.nullable)
result = expected;
else
result = Type::Void().asNullable(); // null sentinel
break;
default: result = Type::error(); break;
} }
break; break;
} }
@ -229,6 +347,12 @@ Type TypeChecker::checkExpr(ASTNode* node, const Type& expected) {
case ASTKind::Identifier: { case ASTKind::Identifier: {
auto* id = (IdentifierNode*)node; auto* id = (IdentifierNode*)node;
result = id->resolvedSymbol ? id->resolvedSymbol->type : Type::error(); result = id->resolvedSymbol ? id->resolvedSymbol->type : Type::error();
// ADR-021: narrowing — bu değişken null kontrolünden geçtiyse non-null say
if (result.nullable && id->parserToken.token) {
std::string name = id->parserToken.token->token;
if (narrowedNonNull_.count(name))
result = result.asNonNull();
}
break; break;
} }
@ -265,23 +389,68 @@ Type TypeChecker::checkExpr(ASTNode* node, const Type& expected) {
} }
Type leftType = checkExpr(bin->Left); Type leftType = checkExpr(bin->Left);
Type rightType = checkExpr(bin->Right);
// Mantıksal // ADR-021: && kısa-devre sağ taraf narrowing — "a != null && a.field"
if (bin->Operator == TokenType::AMPERSAND_AMPERSAND || if (bin->Operator == TokenType::AMPERSAND_AMPERSAND) {
bin->Operator == TokenType::PIPE_PIPE) { auto [narrowVar, isNotNull] = extractNullCheck(bin->Left);
if (!narrowVar.empty() && isNotNull)
narrowedNonNull_.insert(narrowVar);
checkExpr(bin->Right);
if (!narrowVar.empty() && isNotNull)
narrowedNonNull_.erase(narrowVar);
result = Type::Bool(); result = Type::Bool();
break; break;
} }
// Karşılaştırma Type rightType = checkExpr(bin->Right);
if (bin->Operator == TokenType::EQUAL_EQUAL ||
bin->Operator == TokenType::BANG_EQUAL || // Mantıksal (||)
bin->Operator == TokenType::LESS || if (bin->Operator == TokenType::PIPE_PIPE) {
result = Type::Bool();
break;
}
// Eşitlik karşılaştırması: string dahil herhangi tiple çalışır
if (bin->Operator == TokenType::EQUAL_EQUAL ||
bin->Operator == TokenType::BANG_EQUAL) {
result = Type::Bool();
break;
}
// Sıralama karşılaştırması: YALNIZCA sayısal tipler
if (bin->Operator == TokenType::LESS ||
bin->Operator == TokenType::LESS_EQUAL || bin->Operator == TokenType::LESS_EQUAL ||
bin->Operator == TokenType::GREATER || bin->Operator == TokenType::GREATER ||
bin->Operator == TokenType::GREATER_EQUAL) { bin->Operator == TokenType::GREATER_EQUAL) {
result = Type::Bool(); if (leftType.isError() || rightType.isError()) {
result = Type::error(); // önceki hata, sessiz geç
} else if (leftType.isNumeric() && rightType.isNumeric()) {
result = Type::Bool();
} else {
diag_.report("E003", bin->loc,
"Sıralama operatörü yalnızca sayısal tiplerle kullanılabilir: " +
leftType.toString() +
" — string için yalnızca == ve != kullanın");
result = Type::error();
}
break;
}
// ADR-021: katı operand kuralı — non-null bağlamda nullable operand yasak
// (eşitlik / null karşılaştırmaları için geçerli değil)
if (!leftType.isError() && !rightType.isError() &&
(leftType.nullable || rightType.nullable)) {
diag_.report("E003", bin->loc,
"Nullable operand: '" + leftType.toString() + "' ve '" +
rightType.toString() + "' — null kontrolü yapın veya daraltın");
result = Type::error();
break;
}
// String birleştirme: yalnızca + operatörü (ADR-024)
if (bin->Operator == TokenType::PLUS &&
leftType.isString() && rightType.isString()) {
result = Type::String();
break; break;
} }
@ -359,15 +528,34 @@ Type TypeChecker::checkExpr(ASTNode* node, const Type& expected) {
// ── MemberAccess / IndexExpression ───────────────────────────────────── // ── MemberAccess / IndexExpression ─────────────────────────────────────
case ASTKind::MemberAccess: { case ASTKind::MemberAccess: {
auto* ma = (MemberAccessNode*)node; auto* ma = (MemberAccessNode*)node;
checkExpr(ma->object); Type objType = checkExpr(ma->object);
result = Type::error(); // TODO(faz3+): struct alan çözümü // ADR-021: nullable nesne üstünde doğrudan alan erişimi yasak
if (objType.nullable) {
diag_.report("E003", node->loc,
"Nullable tip '" + objType.toString() + "' üstünde doğrudan erişim"
" — if ile null kontrolü yapın");
result = Type::error();
break;
}
if (objType.isStruct()) {
result = table_.getFieldType(objType.structName, ma->member);
if (result.isError())
diag_.report("E001", node->loc,
"'" + objType.structName + "' struct'ında '" + ma->member + "' alanı yok");
} else {
result = Type::error();
}
break; break;
} }
case ASTKind::IndexExpression: { case ASTKind::IndexExpression: {
auto* ie = (IndexExpressionNode*)node; auto* ie = (IndexExpressionNode*)node;
checkExpr(ie->object); Type objType = checkExpr(ie->object);
if (ie->index) checkExpr(ie->index); if (ie->index) checkExpr(ie->index);
result = Type::error(); // TODO(faz3+): array eleman tipi // array eleman tipi
if (objType.isArray() && objType.elementType)
result = *objType.elementType;
else
result = Type::Int(); // varsayılan (tip çıkarımı tam değil)
break; break;
} }

View File

@ -1,6 +1,8 @@
#ifndef SAQUT_SEMANTIC_TYPE_CHECKER #ifndef SAQUT_SEMANTIC_TYPE_CHECKER
#define SAQUT_SEMANTIC_TYPE_CHECKER #define SAQUT_SEMANTIC_TYPE_CHECKER
#include <unordered_set>
#include <string>
#include "symbol/symbol_table.hpp" #include "symbol/symbol_table.hpp"
#include "diagnostic/diagnostic_engine.hpp" #include "diagnostic/diagnostic_engine.hpp"
#include "parser/ast_node.hpp" #include "parser/ast_node.hpp"
@ -31,11 +33,20 @@ private:
// İki sayısal tipin genişlik sırası: int=0, float=1, double=2; -1 = sayısal değil. // İki sayısal tipin genişlik sırası: int=0, float=1, double=2; -1 = sayısal değil.
static int numericRank(const Type& t); static int numericRank(const Type& t);
// ADR-021: if-narrowing — null kontrolü kalıbını ayrıştır
// Dönüş: {varName, isNotNull} — "a != null" → {a, true}; "a == null" → {a, false}; {"", _} = kalıp yok
static std::pair<std::string, bool> extractNullCheck(ASTNode* cond);
// Bir statement her zaman çıkış yapıyor mu? (return/throw/break/continue)
static bool alwaysExits(ASTNode* stmt);
SymbolTable& table_; SymbolTable& table_;
DiagnosticEngine& diag_; DiagnosticEngine& diag_;
Type currentReturnType_; // aktif fonksiyonun beklenen dönüş tipi Type currentReturnType_; // aktif fonksiyonun beklenen dönüş tipi
bool inFunction_ = false; bool inFunction_ = false;
// ADR-021: akış-duyarlı null daraltma — bu kapsamda non-null olduğu bilinen değişkenler
std::unordered_set<std::string> narrowedNonNull_;
}; };
#endif // SAQUT_SEMANTIC_TYPE_CHECKER #endif // SAQUT_SEMANTIC_TYPE_CHECKER

View File

@ -29,6 +29,18 @@ void SymbolCollector::seedBuiltins() {
Type::function(Type::Void(), {}), Type::function(Type::Void(), {}),
SourceLocation{}); SourceLocation{});
if (s) s->isBuiltin = true; if (s) s->isBuiltin = true;
// ADR-025: Error builtin struct — try/catch için
// Alan sırası VM makeErrorValue() ile eşleşmeli: [line, col, message, trace, code]
table_.structLayouts["Error"] = {
{"line", Type::Int()},
{"col", Type::Int()},
{"message", Type::String()},
{"trace", Type::String()},
{"code", Type::String()}
};
table_.define("Error", SymbolKind::Struct, Type::structType("Error"), {});
structFields_["Error"]; // cycle checker'a tanıt
} }
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
@ -77,14 +89,15 @@ void SymbolCollector::pass1Globals(ASTNode* program) {
"'" + st->name + "' zaten bu kapsamda tanımlı"); "'" + st->name + "' zaten bu kapsamda tanımlı");
break; break;
} }
// struct alan isimlerini cycle check için kaydet // structFields_'e her zaman bir giriş aç (typeFromName için gerekli)
structFields_[st->name]; // boş vektör oluşturur; by-value döngü artık referans semantiğiyle meşru (ADR-020)
// structLayouts: tüm alanlar (isim + tip) sırayla — IR üreteci ve tip denetleyici için
for (ASTNode* fieldNode : st->getChildren()) { for (ASTNode* fieldNode : st->getChildren()) {
if (fieldNode->kind == ASTKind::VariableDecl) { if (fieldNode->kind == ASTKind::VariableDecl) {
auto* vd = (VariableDeclNode*)fieldNode; auto* vd = (VariableDeclNode*)fieldNode;
// yalnızca struct tipindeki alanları izle Type ft = typeFromName(vd->varType, vd->loc);
Type ft = Type::fromName(vd->varType); table_.structLayouts[st->name].push_back({vd->name, ft});
if (ft.isError()) // primitif değilse struct tipi olabilir
structFields_[st->name].push_back(vd->varType);
} }
} }
break; break;
@ -124,44 +137,10 @@ void SymbolCollector::pass1Globals(ASTNode* program) {
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
void SymbolCollector::checkStructCycles() { void SymbolCollector::checkStructCycles() {
// white=0 / gray=1 / black=2 // ADR-020: Struct alanları referans semantiği taşır (Object* pointer).
std::unordered_map<std::string, int> color; // By-value gömme yok → sonsuz-boyut döngüsü imkânsız.
for (auto& kv : structFields_) color[kv.first] = 0; // E010 artık üretilmez; bu metot koşullu olarak devre dışı.
// TODO(gelecek): Primitive tipler için by-value gömme eklenirse E010 geri açılır.
std::function<bool(const std::string&)> dfs = [&](const std::string& name) -> bool {
auto it = color.find(name);
if (it == color.end()) return false; // primitif / bilinmeyen → çevrim değil
if (it->second == 1) return true; // gray → back-edge → çevrim!
if (it->second == 2) return false; // black → zaten işlendi
it->second = 1; // gri yap
auto fit = structFields_.find(name);
if (fit != structFields_.end()) {
for (const std::string& dep : fit->second) {
if (dfs(dep)) return true;
}
}
it->second = 2; // siyah yap
return false;
};
for (auto& kv : structFields_) {
if (color[kv.first] == 0) {
// DFS başlat
color[kv.first] = 1;
for (const std::string& dep : kv.second) {
if (dfs(dep)) {
// tanımlama konumunu bulmak için global scope'ta ara
Symbol* s = table_.global()->lookupLocal(kv.first);
SourceLocation loc = s ? s->definitionLoc : SourceLocation{};
diag_.report("E010", loc,
"Döngüsel struct: '" + kv.first + "' by-value sonsuz boyut oluşturur");
break;
}
}
color[kv.first] = 2;
}
}
} }
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
@ -306,6 +285,29 @@ void SymbolCollector::walkStmt(ASTNode* node) {
case ASTKind::ContinueStatement: case ASTKind::ContinueStatement:
break; // yaprak break; // yaprak
// ADR-025: try { body } catch (Error e) { handler }
case ASTKind::TryStatement: {
auto* ts = (TryStatementNode*)node;
if (ts->body) walkStmt(ts->body);
// catch değişkeni catch bloğu kapsamında görünür
if (ts->handler) {
table_.enterScope();
if (!ts->catchVar.empty())
table_.define(ts->catchVar, SymbolKind::Variable,
Type::structType("Error"), {});
walkStmt(ts->handler);
table_.exitScope();
}
break;
}
// ADR-025: throw <ifade>;
case ASTKind::ThrowStatement: {
auto* th = (ThrowStatementNode*)node;
if (th->value) walkExpr(th->value);
break;
}
default: default:
break; break;
} }

View File

@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <unordered_map>
#include "symbol/scope.hpp" #include "symbol/scope.hpp"
class SymbolTable { class SymbolTable {
@ -50,6 +51,26 @@ public:
return result; return result;
} }
// Struct alan düzeni: struct adı → sıralı [(alan adı, tip)] listesi
// Sembol toplayıcı doldurur; tip denetleyici ve IR üreteci okur.
std::unordered_map<std::string, std::vector<std::pair<std::string, Type>>> structLayouts;
int getFieldIndex(const std::string& structName, const std::string& fieldName) const {
auto it = structLayouts.find(structName);
if (it == structLayouts.end()) return -1;
for (int i = 0; i < (int)it->second.size(); i++)
if (it->second[i].first == fieldName) return i;
return -1;
}
Type getFieldType(const std::string& structName, const std::string& fieldName) const {
auto it = structLayouts.find(structName);
if (it == structLayouts.end()) return Type::error();
for (auto& p : it->second)
if (p.first == fieldName) return p.second;
return Type::error();
}
private: private:
Scope* newScope(Scope* p) { Scope* newScope(Scope* p) {
scopes_.push_back(std::make_unique<Scope>(p)); scopes_.push_back(std::make_unique<Scope>(p));

View File

@ -1,8 +1,26 @@
#include "vm/interpreter.hpp" #include "vm/interpreter.hpp"
#include "vm/object.hpp"
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
// ── makeErrorValue ─────────────────────────────────────────────────────────────
// ADR-025: Error struct oluşturur — alan sırası: [line, col, message, trace, code]
Value Interpreter::makeErrorValue(const std::string& message,
const std::string& code,
int line, int col) {
StructObject* obj = heap_.allocStruct(5);
obj->fields[0] = Value::fromInt(line);
obj->fields[1] = Value::fromInt(col);
obj->fields[2] = Value::fromString(message);
obj->fields[3] = Value::fromString(""); // trace — ileride IR satır tablosuyla doldurulacak
obj->fields[4] = Value::fromString(code);
return Value::fromRef(obj);
}
int Interpreter::run() { int Interpreter::run() {
// Global slot'ları sıfırla
globalSlots_.assign(program_.globalCount, Value::fromInt(0));
IRFunction* mainFunction = program_.findFunction("main"); IRFunction* mainFunction = program_.findFunction("main");
if (!mainFunction) if (!mainFunction)
throw std::runtime_error("Çalışma hatası: 'main' fonksiyonu bulunamadı"); throw std::runtime_error("Çalışma hatası: 'main' fonksiyonu bulunamadı");
@ -38,6 +56,10 @@ int Interpreter::run() {
frame.slots[instr.dest] = Value::fromString(instr.stringValue); frame.slots[instr.dest] = Value::fromString(instr.stringValue);
break; break;
case Opcode::LOAD_NULL:
frame.slots[instr.dest] = Value::null();
break;
case Opcode::LOAD_SLOT: case Opcode::LOAD_SLOT:
frame.slots[instr.dest] = frame.slots[instr.src]; frame.slots[instr.dest] = frame.slots[instr.src];
break; break;
@ -59,17 +81,46 @@ int Interpreter::run() {
break; break;
case Opcode::DIV: { case Opcode::DIV: {
int d = frame.slots[instr.right].intValue; int d = frame.slots[instr.right].intValue;
if (d == 0) throw std::runtime_error("Çalışma hatası: sıfıra bölme"); if (d == 0) { pendingThrow_ = makeErrorValue("Sıfıra bölme", "E_DIVZERO"); break; }
frame.slots[instr.dest] = Value::fromInt(frame.slots[instr.left].intValue / d); frame.slots[instr.dest] = Value::fromInt(frame.slots[instr.left].intValue / d);
break; break;
} }
case Opcode::MOD: { case Opcode::MOD: {
int d = frame.slots[instr.right].intValue; int d = frame.slots[instr.right].intValue;
if (d == 0) throw std::runtime_error("Çalışma hatası: sıfıra bölme (mod)"); if (d == 0) { pendingThrow_ = makeErrorValue("Sıfıra bölme (mod)", "E_DIVZERO"); break; }
frame.slots[instr.dest] = Value::fromInt(frame.slots[instr.left].intValue % d); frame.slots[instr.dest] = Value::fromInt(frame.slots[instr.left].intValue % d);
break; break;
} }
// ── Bitsel ────────────────────────────────────────────────────────
case Opcode::BAND:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue & frame.slots[instr.right].intValue);
break;
case Opcode::BOR:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue | frame.slots[instr.right].intValue);
break;
case Opcode::SHL:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue << frame.slots[instr.right].intValue);
break;
case Opcode::SHR:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue >> frame.slots[instr.right].intValue);
break;
case Opcode::BNOT:
frame.slots[instr.dest] = Value::fromInt(~frame.slots[instr.src].intValue);
break;
// ── Global değişken erişimi ────────────────────────────────────────
case Opcode::LOAD_GLOBAL:
frame.slots[instr.dest] = globalSlots_[instr.intValue];
break;
case Opcode::STORE_GLOBAL:
globalSlots_[instr.intValue] = frame.slots[instr.src];
break;
// ── Karşılaştırma ───────────────────────────────────────────────── // ── Karşılaştırma ─────────────────────────────────────────────────
case Opcode::LESS: case Opcode::LESS:
frame.slots[instr.dest] = Value::fromInt( frame.slots[instr.dest] = Value::fromInt(
@ -89,17 +140,25 @@ int Interpreter::run() {
break; break;
case Opcode::EQUAL_EQUAL: { case Opcode::EQUAL_EQUAL: {
auto& lv = frame.slots[instr.left]; auto& rv = frame.slots[instr.right]; auto& lv = frame.slots[instr.left]; auto& rv = frame.slots[instr.right];
int r = (lv.kind == ValueKind::String) int r;
? (lv.stringValue == rv.stringValue ? 1 : 0) if (lv.kind == ValueKind::Ref || rv.kind == ValueKind::Ref)
: (lv.intValue == rv.intValue ? 1 : 0); r = (lv.ref == rv.ref ? 1 : 0); // ADR-023: array/struct kimlik karşılaştırması
else if (lv.kind == ValueKind::String)
r = (lv.stringValue == rv.stringValue ? 1 : 0);
else
r = (lv.intValue == rv.intValue ? 1 : 0);
frame.slots[instr.dest] = Value::fromInt(r); frame.slots[instr.dest] = Value::fromInt(r);
break; break;
} }
case Opcode::NOT_EQUAL: { case Opcode::NOT_EQUAL: {
auto& lv = frame.slots[instr.left]; auto& rv = frame.slots[instr.right]; auto& lv = frame.slots[instr.left]; auto& rv = frame.slots[instr.right];
int r = (lv.kind == ValueKind::String) int r;
? (lv.stringValue != rv.stringValue ? 1 : 0) if (lv.kind == ValueKind::Ref || rv.kind == ValueKind::Ref)
: (lv.intValue != rv.intValue ? 1 : 0); r = (lv.ref != rv.ref ? 1 : 0);
else if (lv.kind == ValueKind::String)
r = (lv.stringValue != rv.stringValue ? 1 : 0);
else
r = (lv.intValue != rv.intValue ? 1 : 0);
frame.slots[instr.dest] = Value::fromInt(r); frame.slots[instr.dest] = Value::fromInt(r);
break; break;
} }
@ -112,6 +171,10 @@ int Interpreter::run() {
if (!frame.slots[instr.cond].isTruthy()) if (!frame.slots[instr.cond].isTruthy())
frame.instructionPointer = instr.jumpTarget; frame.instructionPointer = instr.jumpTarget;
break; break;
case Opcode::JIF_TRUE:
if (frame.slots[instr.cond].isTruthy())
frame.instructionPointer = instr.jumpTarget;
break;
// ── Fonksiyon çağrısı ───────────────────────────────────────────── // ── Fonksiyon çağrısı ─────────────────────────────────────────────
case Opcode::CALL: { case Opcode::CALL: {
@ -148,11 +211,170 @@ int Interpreter::run() {
continue; continue;
} }
// ── Float aritmetik (#44) ─────────────────────────────────────────
case Opcode::LOAD_FLOAT:
frame.slots[instr.dest] = Value::fromFloat(instr.floatValue);
break;
case Opcode::FADD:
frame.slots[instr.dest] = Value::fromFloat(
frame.slots[instr.left].floatValue + frame.slots[instr.right].floatValue);
break;
case Opcode::FSUB:
frame.slots[instr.dest] = Value::fromFloat(
frame.slots[instr.left].floatValue - frame.slots[instr.right].floatValue);
break;
case Opcode::FMUL:
frame.slots[instr.dest] = Value::fromFloat(
frame.slots[instr.left].floatValue * frame.slots[instr.right].floatValue);
break;
case Opcode::FDIV: {
double r = frame.slots[instr.right].floatValue;
if (r == 0.0) { pendingThrow_ = makeErrorValue("Float sıfıra bölme", "E_DIVZERO"); break; }
frame.slots[instr.dest] = Value::fromFloat(frame.slots[instr.left].floatValue / r);
break;
}
case Opcode::FNEG:
frame.slots[instr.dest] = Value::fromFloat(-frame.slots[instr.src].floatValue);
break;
case Opcode::INT_TO_FLOAT:
frame.slots[instr.dest] = Value::fromFloat((double)frame.slots[instr.src].intValue);
break;
case Opcode::FLOAT_TO_INT:
frame.slots[instr.dest] = Value::fromInt((int)frame.slots[instr.src].floatValue);
break;
// ── Struct (ADR-020: referans semantiği) ──────────────────────────
case Opcode::STRUCT_NEW: {
StructObject* obj = heap_.allocStruct(instr.intValue);
frame.slots[instr.dest] = Value::fromRef(obj);
break;
}
case Opcode::FIELD_GET: {
Value& objVal = frame.slots[instr.src];
if (objVal.kind != ValueKind::Ref || !objVal.ref)
throw std::runtime_error("Çalışma hatası: struct değil");
auto* obj = (StructObject*)objVal.ref;
int idx = instr.intValue;
if (idx < 0 || idx >= (int)obj->fields.size())
throw std::runtime_error("Çalışma hatası: geçersiz struct alan indeksi " + std::to_string(idx));
frame.slots[instr.dest] = obj->fields[idx];
break;
}
case Opcode::FIELD_SET: {
Value& objVal = frame.slots[instr.dest];
if (objVal.kind != ValueKind::Ref || !objVal.ref)
throw std::runtime_error("Çalışma hatası: struct değil");
auto* obj = (StructObject*)objVal.ref;
int idx = instr.intValue;
if (idx < 0 || idx >= (int)obj->fields.size())
throw std::runtime_error("Çalışma hatası: geçersiz struct alan indeksi " + std::to_string(idx));
obj->fields[idx] = frame.slots[instr.right];
break;
}
// ── Array (ADR-020: referans semantiği) ───────────────────────────
case Opcode::ARRAY_NEW: {
ArrayObject* arr = heap_.allocArray(instr.intValue);
arr->elements.resize(instr.intValue, Value::fromInt(0));
frame.slots[instr.dest] = Value::fromRef(arr);
break;
}
case Opcode::ARRAY_GET: {
Value& arrVal = frame.slots[instr.left];
if (arrVal.kind != ValueKind::Ref || !arrVal.ref) {
pendingThrow_ = makeErrorValue("Dizi beklendi, farklı tip alındı", "E_TYPE"); break;
}
auto* arr = (ArrayObject*)arrVal.ref;
int idx = frame.slots[instr.right].intValue;
if (idx < 0 || idx >= (int)arr->elements.size()) {
pendingThrow_ = makeErrorValue(
"Dizi sınır dışı (indeks=" + std::to_string(idx) +
", uzunluk=" + std::to_string(arr->elements.size()) + ")", "E_OOB");
break;
}
frame.slots[instr.dest] = arr->elements[idx];
break;
}
case Opcode::ARRAY_SET: {
Value& arrVal = frame.slots[instr.dest];
if (arrVal.kind != ValueKind::Ref || !arrVal.ref) {
pendingThrow_ = makeErrorValue("Dizi beklendi, farklı tip alındı", "E_TYPE"); break;
}
auto* arr = (ArrayObject*)arrVal.ref;
int idx = frame.slots[instr.left].intValue;
if (idx < 0 || idx >= (int)arr->elements.size()) {
pendingThrow_ = makeErrorValue(
"Dizi sınır dışı (indeks=" + std::to_string(idx) +
", uzunluk=" + std::to_string(arr->elements.size()) + ")", "E_OOB");
break;
}
arr->elements[idx] = frame.slots[instr.right];
break;
}
case Opcode::ARRAY_LEN: {
Value& arrVal = frame.slots[instr.src];
if (arrVal.kind != ValueKind::Ref || !arrVal.ref)
throw std::runtime_error("Çalışma hatası: dizi değil");
auto* arr = (ArrayObject*)arrVal.ref;
frame.slots[instr.dest] = Value::fromInt((int)arr->elements.size());
break;
}
// ── String (ADR-024: immutable değer-tipi, içerik ==) ────────────
case Opcode::STRING_CONCAT:
frame.slots[instr.dest] = Value::fromString(
frame.slots[instr.left].stringValue +
frame.slots[instr.right].stringValue);
break;
// ── Hata yönetimi (ADR-025) ──────────────────────────────────────
case Opcode::ENTER_TRY:
tryStack_.push_back({callStack_.size(), instr.jumpTarget, instr.dest});
break;
case Opcode::LEAVE_TRY:
if (!tryStack_.empty()) tryStack_.pop_back();
break;
case Opcode::THROW:
pendingThrow_ = frame.slots[instr.src];
break;
// ── FFI ─────────────────────────────────────────────────────────── // ── FFI ───────────────────────────────────────────────────────────
case Opcode::CALLHOST: case Opcode::CALLHOST:
executeHostFunction(instr.functionName, frame.slots, instr.argSlots); executeHostFunction(instr.functionName, frame.slots, instr.argSlots);
break; break;
} }
// ── pendingThrow_ işle: try varsa catch'e unwind, yoksa fırlat ───
if (pendingThrow_.has_value()) {
Value errVal = std::move(*pendingThrow_);
pendingThrow_.reset();
if (!tryStack_.empty()) {
TryFrame tf = tryStack_.back();
tryStack_.pop_back();
// catch bloğunun bulunduğu frame'e unwind
while (callStack_.size() > tf.callStackDepth)
callStack_.pop_back();
// Error'ı catch değişkenine bağla ve catch etiketine atla
callStack_.back().slots[tf.errorSlot] = errVal;
callStack_.back().instructionPointer = tf.catchTarget;
} else {
// Yakalanmamış hata — mesajı çıkar ve C++ exception olarak yükselt
std::string msg = "Yakalanmamış hata";
if (errVal.kind == ValueKind::Ref && errVal.ref) {
auto* s = static_cast<StructObject*>(errVal.ref);
if ((int)s->fields.size() > 2 &&
s->fields[2].kind == ValueKind::String)
msg = s->fields[2].stringValue;
} else if (errVal.kind == ValueKind::String) {
msg = errVal.stringValue;
}
throw std::runtime_error(msg);
}
continue;
}
} }
return 0; return 0;
@ -164,8 +386,7 @@ void Interpreter::executeHostFunction(const std::string& name,
if (name == "print") { if (name == "print") {
if (!argSlots.empty()) { if (!argSlots.empty()) {
const Value& val = slots[argSlots[0]]; const Value& val = slots[argSlots[0]];
if (val.kind == ValueKind::String) std::cout << val.stringValue << "\n"; std::cout << val.toString() << "\n";
else std::cout << val.intValue << "\n";
} }
return; return;
} }

View File

@ -14,8 +14,17 @@
#define SAQUT_VM_INTERPRETER #define SAQUT_VM_INTERPRETER
#include <vector> #include <vector>
#include <optional>
#include "ir/ir_program.hpp" #include "ir/ir_program.hpp"
#include "vm/call_frame.hpp" #include "vm/call_frame.hpp"
#include "vm/object.hpp"
// ADR-025: try bloğu girişinde yığına eklenen kayıt
struct TryFrame {
size_t callStackDepth; // ENTER_TRY anındaki callStack_.size() — unwind için
int catchTarget; // catch bloğunun IR instruction indeksi
int errorSlot; // catch değişkeninin slot numarası (catch frame'inde)
};
class Interpreter { class Interpreter {
public: public:
@ -26,8 +35,17 @@ public:
int run(); int run();
private: private:
IRProgram& program_; IRProgram& program_;
std::vector<CallFrame> callStack_; std::vector<CallFrame> callStack_;
std::vector<Value> globalSlots_;
Heap heap_;
std::vector<TryFrame> tryStack_; // ADR-025: aktif try çerçeveleri
std::optional<Value> pendingThrow_; // bekleyen istisna değeri
// Error StructObject oluştur (ADR-025): [line, col, message, trace, code]
Value makeErrorValue(const std::string& message,
const std::string& code = "",
int line = 0, int col = 0);
// Host (C++) fonksiyon çağrısı — şu an sadece "print" destekli // Host (C++) fonksiyon çağrısı — şu an sadece "print" destekli
void executeHostFunction(const std::string& name, void executeHostFunction(const std::string& name,

78
src/vm/object.hpp Normal file
View File

@ -0,0 +1,78 @@
#ifndef SAQUT_VM_OBJECT
#define SAQUT_VM_OBJECT
#include <vector>
// ADR-022: GC-hazır nesne modeli (v1: toplama yok, sadece header + liste kancası).
// Her heap nesnesi bu yapıdan türer.
// marked + next: mark-sweep için hazır; v1'de kullanılmaz.
// TODO(#56): mark-sweep v2 — Heap::collect() bu header'ı kullanacak.
enum class ObjectType { Array, Struct };
struct Object {
ObjectType type;
bool marked = false; // mark-sweep için (v2); şimdilik kullanılmaz
Object* next = nullptr; // "tüm nesneler" intrusive listesi
};
// Forward declare — Value, Object*'ı taşır; Object, Value içerir.
struct Value;
struct ArrayObject : Object {
std::vector<Value> elements;
explicit ArrayObject(int capacity = 0) {
type = ObjectType::Array;
if (capacity > 0) elements.reserve(capacity);
}
};
// ADR-020: Struct = referans semantiği. Alanlar sıra indeksiyle erişilir.
struct StructObject : Object {
std::vector<Value> fields;
explicit StructObject(int fieldCount = 0) {
type = ObjectType::Struct;
fields.resize(fieldCount); // Value::fromInt(0) ile başlatılır (varsayılan)
}
};
// ── Heap ─────────────────────────────────────────────────────────────────────
// Tüm nesneleri intrusive listede tutar. v1'de serbest bırakma yok.
// TODO(#56): mark-sweep v2 — collect() kök taraması yapacak, ölü nesneleri silecek.
struct Heap {
Object* head = nullptr;
int allocCount = 0;
ArrayObject* allocArray(int capacity = 0) {
auto* obj = new ArrayObject(capacity);
obj->next = head;
head = obj;
allocCount++;
return obj;
}
StructObject* allocStruct(int fieldCount) {
auto* obj = new StructObject(fieldCount);
obj->next = head;
head = obj;
allocCount++;
return obj;
// TODO(#56): mark-sweep kök taraması buradan
}
// v1: process exit'te OS toplar; yıkıcı tüm nesneleri siler.
~Heap() {
Object* cur = head;
while (cur) {
Object* nxt = cur->next;
delete cur;
cur = nxt;
}
}
Heap() = default;
Heap(const Heap&) = delete;
Heap& operator=(const Heap&) = delete;
};
#endif // SAQUT_VM_OBJECT

View File

@ -1,62 +1,90 @@
// ============================================================================
// saQut VM — Value (Çalışma Zamanı Değer)
//
// Bir saQut değerinin bellekteki temsilidir.
//
// ŞU AN SADECE INT:
// fibonacci.sqt tamamen int kullanır, bu dikey dilim için int yeterli.
// İleride float, bool, string eklenmesi için "kind" alanı iskelet olarak bırakıldı.
//
// BOOLEAN OLARAK KULLANIM:
// JIF_FALSE talimatı değerin 0 olup olmadığına bakar.
// 0 = yanlış, sıfır-dışı = doğru. C geleneği.
// ============================================================================
#ifndef SAQUT_VM_VALUE #ifndef SAQUT_VM_VALUE
#define SAQUT_VM_VALUE #define SAQUT_VM_VALUE
#include <string> #include <string>
#include <sstream>
#include <iomanip>
#include <stdexcept>
// Gelecekte float/bool/string eklendiğinde burası genişleyecek. // Forward — Object tam tanımı object.hpp'de; Value onu pointer olarak taşır.
// Şimdilik sadece int. struct Object;
// ADR-020: Primitive (int/bool) = değer; bileşik (array/struct/string) = referans.
// ADR-021: Null = nullable referansların null değeri (saQut'ta `null` anahtar sözcüğü).
// Bool ayrı kind değil — boolean sonuçlar int olarak saklanır (0=yanlış, sıfır-dışı=doğru).
enum class ValueKind { enum class ValueKind {
Int, Int,
Float, // #44: float/double tek kind; floatValue alanı taşır
String, String,
// Float, // TODO(vm-genişletme) Ref, // ADR-020: array/struct nesnesine Object* referansı
// Bool, // TODO(vm-genişletme) Null, // ADR-021: nullable referansın null değeri (saQut kaynağında `null`)
}; };
struct Value { struct Value {
ValueKind kind = ValueKind::Int; ValueKind kind = ValueKind::Int;
int intValue = 0; int intValue = 0;
std::string stringValue; // yalnızca kind == String için geçerli double floatValue = 0.0; // kind == Float için
std::string stringValue; // kind == String için
Object* ref = nullptr; // kind == Ref için
static Value fromInt(int n) { static Value fromInt(int n) {
Value v; Value v; v.kind = ValueKind::Int; v.intValue = n; return v;
v.kind = ValueKind::Int; }
v.intValue = n;
return v; static Value fromFloat(double d) {
Value v; v.kind = ValueKind::Float; v.floatValue = d; return v;
} }
static Value fromString(std::string s) { static Value fromString(std::string s) {
Value v; Value v; v.kind = ValueKind::String; v.stringValue = std::move(s); return v;
v.kind = ValueKind::String; }
v.stringValue = std::move(s);
return v; static Value fromRef(Object* obj) {
Value v; v.kind = ValueKind::Ref; v.ref = obj; return v;
}
static Value null() {
Value v; v.kind = ValueKind::Null; return v;
} }
// JIF_FALSE için: int 0 = yanlış, boş string = yanlış, diğer = doğru
bool isTruthy() const { bool isTruthy() const {
if (kind == ValueKind::Int) return intValue != 0; switch (kind) {
if (kind == ValueKind::String) return !stringValue.empty(); case ValueKind::Int: return intValue != 0;
case ValueKind::Float: return floatValue != 0.0;
case ValueKind::String: return !stringValue.empty();
case ValueKind::Ref: return ref != nullptr;
case ValueKind::Null: return false;
}
return false; return false;
} }
// Okunabilir metin — dump ve hata mesajları için std::string toString() const {
switch (kind) {
case ValueKind::Int: return std::to_string(intValue);
case ValueKind::Float: {
// Tam sayıysa "3.0", değilse "3.14" gibi — gereksiz sıfırları kırp
std::ostringstream oss;
oss << std::setprecision(10) << floatValue;
std::string s = oss.str();
// Nokta yoksa ".0" ekle (saQut float değerleri her zaman nokta içerir)
if (s.find('.') == std::string::npos && s.find('e') == std::string::npos)
s += ".0";
return s;
}
case ValueKind::String: return stringValue;
case ValueKind::Ref: return "<ref>";
case ValueKind::Null: return "null";
}
return "?";
}
std::string typeName() const { std::string typeName() const {
switch (kind) { switch (kind) {
case ValueKind::Int: return "int"; case ValueKind::Int: return "int";
case ValueKind::Float: return "float";
case ValueKind::String: return "string"; case ValueKind::String: return "string";
case ValueKind::Ref: return "ref";
case ValueKind::Null: return "null";
} }
return "?"; return "?";
} }

View File

@ -0,0 +1,5 @@
5
6
12
3
1

View File

@ -0,0 +1,8 @@
int main() {
print(2 + 3);
print(10 - 4);
print(3 * 4);
print(10 / 3);
print(10 % 3);
return 0;
}

View File

@ -0,0 +1,4 @@
2
1
0
2

View File

@ -0,0 +1,27 @@
// B8: %= bileşik atama doğru IR üretmeli.
// Elle hesap: 17%5=2, 10%3=1, 0%4=0, zincir: 20+5=25-3=22*2=44/4=11%3=2
int main() {
int a = 17;
a %= 5;
print(a); // 2
int b = 10;
b %= 3;
print(b); // 1
int c = 0;
c %= 4;
print(c); // 0
// Tüm bileşik atamalar zinciri (regresyon)
int x = 20;
x += 5; // 25
x -= 3; // 22
x *= 2; // 44
x /= 4; // 11
x %= 3; // 2
print(x); // 2
return 0;
}

View File

@ -0,0 +1 @@
sıfıra bölme \(mod\)

View File

@ -0,0 +1,8 @@
// Runtime test: a %= 0 → çalışma zamanı sıfıra bölme hatası vermeli.
int main() {
int a = 7;
a %= 0;
print(a);
return 0;
}

View File

@ -0,0 +1,6 @@
7
9
3
3
1
11

View File

@ -0,0 +1,9 @@
int main() {
print(1 + 2 * 3);
print((1 + 2) * 3);
print(10 - 4 - 3);
print(10 / 3);
print(10 % 3);
print(2 + 3 * 4 - 6 / 2);
return 0;
}

View File

@ -0,0 +1,4 @@
99
1
0
2

View File

@ -0,0 +1,15 @@
void degistir(int[] a) {
a[0] = 99;
}
int main() {
int[] x = [1, 2, 3];
degistir(x);
print(x[0]);
int[] y = x;
print(y == x);
int[] z = [1, 2, 3];
print(z == x);
print(x[1]);
return 0;
}

View File

@ -0,0 +1,5 @@
8
14
24
6
-1

View File

@ -0,0 +1,10 @@
int main() {
int a = 12;
int b = 10;
print(a & b);
print(a | b);
print(a << 1);
print(a >> 1);
print(~0);
return 0;
}

View File

@ -0,0 +1,4 @@
6
14
56
28

View File

@ -0,0 +1,12 @@
int main() {
int x = 15;
x &= 6;
print(x);
x |= 8;
print(x);
x <<= 2;
print(x);
x >>= 1;
print(x);
return 0;
}

View File

@ -0,0 +1,3 @@
yakalandi
Sıfıra bölme
E_DIVZERO

View File

@ -0,0 +1,14 @@
// ADR-025: temel try/catch — runtime hatasını yakala
int main() {
try {
int x = 10 / 0;
print("erişilmez");
} catch (Error e) {
print("yakalandi");
print(e.message);
print(e.code);
}
return 0;
}

View File

@ -0,0 +1,4 @@
OOB yakalandi
E_OOB
throw yakalandi
devam

View File

@ -0,0 +1,29 @@
// ADR-025: throw + iç içe fonksiyon çağrısında unwind + array OOB
int riskli() {
int arr[3] = [1, 2, 3];
return arr[10];
}
int main() {
// Dış fonksiyonda throw
try {
riskli();
print("erişilmez");
} catch (Error e) {
print("OOB yakalandi");
print(e.code);
}
// Açık throw — string değer atıp catch et
try {
throw "kullanici hatasi";
} catch (Error e) {
print("throw yakalandi");
}
// Catch sonrası akış devam etmeli
print("devam");
return 0;
}

View File

@ -0,0 +1,2 @@
55
55

View File

@ -0,0 +1,24 @@
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));
print(fibonacciIterative(n));
return 0;
}

View File

@ -0,0 +1,5 @@
5.14
6.28
1.14
1.57
1.0

View File

@ -0,0 +1,11 @@
int main() {
float x = 3.14;
float y = 2.0;
print(x + y);
print(x * y);
print(x - y);
print(x / y);
float z = 1;
print(z);
return 0;
}

View File

@ -0,0 +1,3 @@
5
105
8

View File

@ -0,0 +1,12 @@
int counter = 0;
int total = 100;
int main() {
counter = 5;
total = total + counter;
print(counter);
print(total);
counter += 3;
print(counter);
return 0;
}

View File

@ -0,0 +1,2 @@
10
20

View File

@ -0,0 +1,9 @@
int base = 10;
int doubled = 0;
int main() {
doubled = base * 2;
print(base);
print(doubled);
return 0;
}

View File

@ -0,0 +1,5 @@
1
0
1
0
1

View File

@ -0,0 +1,28 @@
// ! operatörü golden testi — değişken operandlar (bozuk olan yol).
// Sabit operandlar sabit katlama tarafından derleme zamanında hesaplanır;
// bu test IR üretim yolunu zorlayan değişken operandlar kullanır.
//
// Tanım: !x → sıfırsa 1, değilse 0. Sonuç her zaman 0 ya da 1.
int main() {
int z = 0;
int n = 5;
// Temel: !0 → 1, !5 → 0
print(!z);
print(!n);
// Çift değil normalleştirme: !!5 → 1, !!0 → 0
print(!!n);
print(!!z);
// if (!x) dallanma: z=0 iken gövde çalışmalı, n=5 iken çalışmamalı
if (!z) {
print(1);
}
if (!n) {
print(0);
}
return 0;
}

View File

@ -0,0 +1,5 @@
S
evet_and
evet_or1
S
evet_or2

View File

@ -0,0 +1,43 @@
// Kısa devre (short-circuit) değerlendirmesini kanıtlayan golden test.
//
// Amaç: sadece "doğru sonuç veriyor" değil, sağ taraftaki yan etkinin
// ATLANDIĞINI çıktıdan kanıtlamak. Tüm operandlar değişken (sabit değil)
// — sabit katlama yolunu değil, IR üretim yolunu test eder.
//
// Beklenen çıktı analizi:
// f=0 && side() → kısa devre → "S" ÇIKMIYOR
// t=1 && side() → b çalışır → "S" ÇIKIYOR, "evet_and"
// t=1 || side() → kısa devre → "S" ÇIKMIYOR, "evet_or1"
// f=0 || side() → b çalışır → "S" ÇIKIYOR, "evet_or2"
int side() {
print("S");
return 1;
}
int main() {
int f = 0;
int t = 1;
// && false-left: side() atlanmalı, "S" çıkmamalı
if (f && side()) {
print("hatali_and");
}
// && true-left: side() çalışmalı → "S" çıkar, sonra "evet_and"
if (t && side()) {
print("evet_and");
}
// || true-left: side() atlanmalı, "S" çıkmamalı, yine de "evet_or1" çıkar
if (t || side()) {
print("evet_or1");
}
// || false-left: side() çalışmalı → "S" çıkar, sonra "evet_or2"
if (f || side()) {
print("evet_or2");
}
return 0;
}

View File

@ -0,0 +1,9 @@
0
1
2
0
1
2
0
1
2

View File

@ -0,0 +1,18 @@
int main() {
int i = 0;
while (i < 3) {
print(i);
i = i + 1;
}
int j = 0;
do {
print(j);
j = j + 1;
} while (j < 3);
for (int k = 0; k < 3; k = k + 1) {
print(k);
}
return 0;
}

View File

@ -0,0 +1 @@
5

View File

@ -0,0 +1,8 @@
int main() {
int x = 5;
do {
print(x);
x = x + 1;
} while (x < 0);
return 0;
}

View File

@ -0,0 +1,4 @@
1
2
3
5

View File

@ -0,0 +1,25 @@
// B4 regresyon testi: do-while koşulu 1-olmayan sıfır-dışı değer üretince
// döngü yanlışlıkla çıkmamalı ("== 1" geçici çözümü bu hatayı veriyordu).
//
// Test 1: koşul 2 üretiyor — döngü 3 kez dönmeli (i: 0→1→2, çıkış i==3)
// Test 2: koşul 0 olunca düzgün çıkıyor — döngü 1 kez dönmeli
int main() {
// Koşul 2 (1-olmayan truthy): döngü erken çıkmamalı
int i = 0;
do {
i = i + 1;
print(i);
} while (i < 3);
// i<3 sonucu: i=1→1, i=2→1, i=3→0; çıktı: 1 2 3
// Koşul 0: tek iterasyon, gövde bir kez çalışır
int j = 5;
do {
print(j);
j = 0;
} while (j);
// j=5 → print(5), j=0 → while(0) → çıkış; çıktı: 5
return 0;
}

View File

@ -0,0 +1,5 @@
1
3
5
1
2

View File

@ -0,0 +1,24 @@
// for döngüsünde break ve continue golden testi.
//
// continue kanıtı: 2 ve 4 atlanır ama güncelleme (i++) hala çalışır.
// Eğer continue güncellemeyi atlasaydı i==2'de sonsuz döngüye girerdi.
// 5'in çıktıda görünmesi güncellemenin çalıştığını kanıtlar.
//
// break kanıtı: i==3'te erken çık — 3, 4, 5 görünmemeli.
int main() {
int i = 0;
for (i = 1; i <= 5; i = i + 1) {
if (i == 2) { continue; }
if (i == 4) { continue; }
print(i);
}
for (i = 1; i <= 5; i = i + 1) {
if (i == 3) { break; }
print(i);
}
return 0;
}

View File

@ -0,0 +1,6 @@
1
1
2
1
3
1

View File

@ -0,0 +1,21 @@
// İç içe döngü: içteki break sadece içteki döngüyü etkiler.
// Döngü bağlamı yığınının doğru çalıştığını kanıtlar.
//
// Beklenen: her dış iterasyonda j=1 yazdırılır, j=2'de inner break.
// Dış döngü i=1,2,3 boyunca devam eder — inner break dışarıya sızmaz.
int main() {
int i = 1;
while (i <= 3) {
int j = 1;
while (j <= 3) {
if (j == 2) { break; }
print(i);
print(j);
j = j + 1;
}
i = i + 1;
}
return 0;
}

View File

@ -0,0 +1,7 @@
1
2
4
5
1
2
3

View File

@ -0,0 +1,22 @@
// while döngüsünde break ve continue golden testi.
int main() {
int i = 0;
// continue: 3'ü atla
while (i < 5) {
i = i + 1;
if (i == 3) { continue; }
print(i);
}
// break: 4'te çık
i = 0;
while (i < 10) {
i = i + 1;
if (i == 4) { break; }
print(i);
}
return 0;
}

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,21 @@
// ADR-021: && sağ taraf narrowing
int? getValue() {
return 7;
}
bool check(int? v) {
if (v != null && v > 5) {
return true;
}
return false;
}
int main() {
bool r = check(getValue());
if (r) {
print(1);
} else {
print(0);
}
return 0;
}

View File

@ -0,0 +1,2 @@
42
0

Some files were not shown because too many files have changed in this diff Show More