chore: CLAUDE.md güncelle + gen_large.py + large.sqt ekle

- CLAUDE.md: Faz 2/3 tamamlandı, yeni komutlar (check), nlohmann/json,
  semantic/ klasörü, performans optimizasyonu notları güncellendi
- scripts/gen_large.py: 2.3MB geçerli .sqt dosyası üreten benchmark script'i
- examples/large.sqt: 5000 fonksiyon, 90K satır, performans test fixture'ı

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
abdussamedulutas 2026-06-18 18:40:30 +03:00
parent 2b9888c021
commit 8453dcd796
6 changed files with 90935 additions and 473 deletions

102
CLAUDE.md Normal file
View File

@ -0,0 +1,102 @@
# CLAUDE.md — saQut Proje Bağlamı
> Bu dosya her oturumda yüklenir. Amaç: projenin kimliğini, kilitli kararları,
> mevcut durumu ve çalışma konvansiyonlarını hızlıca hatırlatmak.
## İletişim
- **Kullanıcıyla TÜM yazışmalar Türkçe.** (Sahibi: Abdussamed ULUTAŞ.)
## Proje nedir?
saQut, **programlanabilir ve incelenebilir bir derleyici** — bir "alet çantası"
(toolbox). Asıl varlık sebebi dilin kendisi değil, **derleme sürecinin her
aşamasının dışarıdan görülebilir/müdahale edilebilir olması**: token'lar, AST,
sembol tablosu, optimizasyon öncesi/sonrası ve IR ayrı ayrı incelenebilir.
Uygulama dili **C++** (header-only eğilimli, ADR-003). CMake + Ninja. `build/`
git'te izlenir.
## Kilitli kararlar (değiştirme — gerekçeler ADR'lerde)
- **Çalıştırma modeli: IR + bytecode VM (yorumlayıcı döngü).** Tree-walker DEĞİL,
gerçek makine-kodu JIT DEĞİL (kapsam dışı; öncelik determinizm + incelenebilirlik,
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
allocator yok. (ADR-015)
- **Dil kimliği:** prosedürel, C-ailesi sözdizimi, value semantics, zorunlu
class/main boilerplate yok. **Yok:** class/OOP, closure, generic, kullanıcı
pointer'ı (`*`/`&`), auto/tip çıkarımı, gizli int↔float (tek istisna sabit
folding). **Var:** struct, tipli fonksiyonlar, array (`int[]`). `interface`
**ertelendi** (reddedilmedi, ADR-018).
- **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
(parent pointer'lar + sembol tablosu remap edilir, ADR-007). Fixpoint döngüsü +
iterasyon tavanı (`maxFixpointRounds`, ADR-009).
- **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
by-value struct → E010. (ADR-010/011)
- **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"
değil; kripto asla elle yazılmaz (ADR-017).
## Mevcut durum (yapılan vs planlanan)
- **Çalışıyor:** lexer, tokenizer, Pratt parser, AST, AST'nin JSON serileştirmesi,
CLI iskeleti (`tokens`/`ast`/`symbols`/`run`), konum takibi, basit aritmetiği
düşüren minimal IR deneyi.
- **Planlı (henüz YOK):** sembol tablosu, semantik analiz, tip sistemi, diagnostic
motoru, optimizasyon, IR+bytecode VM ile çalıştırma.
- **Birinci kilometre taşı ("bitti" tanımı):** `examples/fibonacci.sqt`
(recursive + iterative) derlenip çalıştırılabilmeli.
- **İlke:** Önce uçtan uca tek **dikey dilim**, sonra çerçeve. Erken soyutlamadan kaçın.
## Belge haritası
- `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/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ı (Faz 04 → fibonacci).
- `docs/transkript-frontend-tasarim.md` — tasarım oturumu transkripti.
- `examples/fibonacci.sqt` — geçerli referans program.
- `examples/parser-stress/` — yalnızca parser'ı zorlayan, **geçerli olmayan** fixture'lar.
## Gitea issue yönetimi
- Repo: `git.saqut.com/saqut/saqut-compiler` (Gitea). Cloudflare, Python-urllib
User-Agent'ını banlıyor → tarayıcı User-Agent'ı şart.
- `scripts/gitea.py` — API istemcisi (`~/.git-credentials`'tan kimlik okur).
Komutlar: `list/get/create/edit/comment`. Toplu issue üretimi:
`scripts/create_issues.py`, `create_future_issues.py`, `create_syntax_test_issues.py`.
- **Issue yapısı (bu oturumda kuruldu):**
- **#6973** `faz-plani` — Faz 04 (Tip+Diagnostic, AST refactor, Symbol Table,
Semantik Analiz, Optimizasyon). Format: Giriş/Gelişme/Sonuç-Başarı Kriterleri +
mühendis-olmayan analiz.
- **#7498, #111** `fikir` — IR/VM tasarımı, modül/import, tip genişletmeleri
(decimal/date/enum/string), FFI/builtin/stdlib, tooling (LSP/highlight/fmt),
gelecek vizyonu (time-travel debug, WASM playground, test bloğu, paket yöneticisi).
Format: Giriş/Gelişme/**Açık Sorular** (başarı kriteri YOK).
- **#99105** `test-senaryosu` — kaynak kod + beklenen çıktı içeren golden-test'ler.
- **#106110** `cli-ux`/`kalite-mimari` — CLI fikirleri, C/Java/Go tarzı tavsiyeler.
- LSP (#91) ve CLI (#107) **Tier 04** katmanlı yetenek haritası olarak yazıldı;
#111 ekosistem bağımlılık sırası.
## Lisans (LICENSE.md — bu oturumda yeniden yazıldı)
- **Model:** "Kaynağıık — Ticari Kullanımı Kısıtlı" (açık kaynak ama **özgür
yazılım değil**). Önceki GPL-tarzı copyleft metin niyetle çelişiyordu, değiştirildi.
- **Çekirdek ilke:** Gelir saQut'un **ürettiği Çıktıdan** elde edilir, **saQut'un
kendisinden değil.**
- **Serbest (ticari dahil):** kod yazmak/derlemek, üretilen programları/exe/işlenmiş
veriyi satmak, derleyiciyi özel araç olarak iç kullanım.
- **İzin gerektirir (telif sahibinden):** derleyiciyi 3. tarafa kurup ücret almak,
Web-IDE/derleme servisi, canlı backend motoru, otomasyon/AI aracı, alt-bileşen
gömme, iç parçaları (AST/optimizatör) ticari yeniden kullanım. Runtime'a bağımlı
sürümlerde sunucu-tarafı ticari kullanım da bu kapsamda.
- **Maddeler:** §7 Katkı (PR herkese açık, **merge kararı yalnızca Abdussamed
ULUTAŞ**; katkı sahipleri ticari lisanslama dâhil hakları telif sahibine verir),
§8 Patent (lisans + dava açana otomatik fesih), §9 Marka ("saQut" adı korunur),
§11 Fesih (ihlalde otomatik + 30 gün düzeltme; edinilmiş Çıktı korunur).
- Üç dilde (TR/EN/DE), TR esas. Ticari lisans iletişimi: saqutsoftware+gitea@gmail.com
- **Not:** Bespoke lisans; ciddi ticari aşamada hukukçu gözden geçirmesi önerilir.
Telif yalnızca kodu/belgeyi korur, **fikri/tasarımı değil** (sıfırdan yeniden
yazım engellenemez); isim ise marka ile korunur.
## Çalışma konvansiyonları
- Commit mesajları sonunda: `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`.
- Ana dal `master`; 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
kullanıcı tarafından elle yapıştırılıyor.

View File

@ -20,12 +20,11 @@ CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
//Path to a program.
CMAKE_AR:FILEPATH=/usr/bin/ar
//Choose the type of build, options are: None Debug Release RelWithDebInfo
// MinSizeRel ...
//No help, variable specified on the command line.
CMAKE_BUILD_TYPE:STRING=Debug
//CXX compiler
CMAKE_CXX_COMPILER:STRING=/usr/bin/c++
//No help, variable specified on the command line.
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++
//A wrapper around 'ar' adding the appropriate '--plugin' option
// for the GCC compiler
@ -50,6 +49,9 @@ CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
//Flags used by the CXX compiler during RELWITHDEBINFO builds.
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
//No help, variable specified on the command line.
CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc
//Path to a program.
CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
@ -71,8 +73,8 @@ CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Enable/Disable output of build database during the build.
CMAKE_EXPORT_BUILD_DATABASE:BOOL=
//Enable/Disable output of compile commands during generation.
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
//No help, variable specified on the command line.
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE
//Value Computed by CMake.
CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/pkgRedirects

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
rule CXX_SCAN__saqut_Debug
depfile = $DEP_FILE
command = /usr/bin/c++ $DEFINES $INCLUDES $FLAGS -E -x c++ $in -MT $DYNDEP_INTERMEDIATE_FILE -MD -MF $DEP_FILE -fmodules-ts -fdeps-file=$DYNDEP_INTERMEDIATE_FILE -fdeps-target=$OBJ_FILE -fdeps-format=p1689r5 -o $PREPROCESSED_OUTPUT_FILE
command = /usr/bin/g++ $DEFINES $INCLUDES $FLAGS -E -x c++ $in -MT $DYNDEP_INTERMEDIATE_FILE -MD -MF $DEP_FILE -fmodules-ts -fdeps-file=$DYNDEP_INTERMEDIATE_FILE -fdeps-target=$OBJ_FILE -fdeps-format=p1689r5 -o $PREPROCESSED_OUTPUT_FILE
description = Scanning $in for CXX dependencies
@ -37,7 +37,7 @@ rule CXX_DYNDEP__saqut_Debug
rule CXX_COMPILER__saqut_scanned_Debug
depfile = $DEP_FILE
deps = gcc
command = ${LAUNCHER}${CODE_CHECK}/usr/bin/c++ $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -fmodules-ts -fmodule-mapper=$DYNDEP_MODULE_MAP_FILE -MD -fdeps-format=p1689r5 -x c++ -o $out -c $in
command = ${LAUNCHER}${CODE_CHECK}/usr/bin/g++ $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -fmodules-ts -fmodule-mapper=$DYNDEP_MODULE_MAP_FILE -MD -fdeps-format=p1689r5 -x c++ -o $out -c $in
description = Building CXX object $out
@ -47,7 +47,7 @@ rule CXX_COMPILER__saqut_scanned_Debug
rule CXX_COMPILER__saqut_unscanned_Debug
depfile = $DEP_FILE
deps = gcc
command = ${LAUNCHER}${CODE_CHECK}/usr/bin/c++ $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in
command = ${LAUNCHER}${CODE_CHECK}/usr/bin/g++ $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in
description = Building CXX object $out
@ -57,7 +57,7 @@ rule CXX_COMPILER__saqut_unscanned_Debug
rule CXX_EXECUTABLE_LINKER__saqut_Debug
depfile = $DEP_FILE
deps = gcc
command = $PRE_LINK && /usr/bin/c++ $FLAGS $LINK_FLAGS $in -o $TARGET_FILE $LINK_PATH $LINK_LIBRARIES && $POST_BUILD
command = $PRE_LINK && /usr/bin/g++ $FLAGS $LINK_FLAGS $in -o $TARGET_FILE $LINK_PATH $LINK_LIBRARIES && $POST_BUILD
description = Linking CXX executable $TARGET_FILE
restat = $RESTAT

90581
examples/large.sqt Normal file

File diff suppressed because it is too large Load Diff

153
scripts/gen_large.py Normal file
View File

@ -0,0 +1,153 @@
"""
saQut büyük kaynak dosyası üretici.
Sözdizimsel ve semantik olarak geçerli, çeşitli yapılar içeren
gerçekçi bir .sqt dosyası üretir.
Hedef: ~1 MB
"""
import sys
import random
random.seed(42)
lines = []
def emit(s=""):
lines.append(s)
# ── Başlık ────────────────────────────────────────────────────────────────────
emit("// saQut büyük kaynak dosyası — otomatik üretildi (gen_large.py)")
emit("// Amaç: ast / symbols / check komutları için performans ölçümü")
emit()
# ── Struct tanımları ──────────────────────────────────────────────────────────
STRUCT_COUNT = 20
for i in range(STRUCT_COUNT):
emit(f"struct Vec{i} {{")
emit(f" int x;")
emit(f" int y;")
emit(f" int z;")
emit(f" float w;")
emit(f"}}")
emit()
# ── Global değişkenler ────────────────────────────────────────────────────────
for i in range(50):
emit(f"int g_{i} = {i * 3 + 1};")
emit()
# ── Yardımcı: rastgele aritmetik ifade (derinlik sınırlı) ─────────────────────
def expr(depth=0, vars=None):
if vars is None:
vars = ["a", "b", "c", "x", "n"]
if depth >= 3 or random.random() < 0.35:
choice = random.random()
if choice < 0.5 and vars:
return random.choice(vars)
elif choice < 0.8:
return str(random.randint(1, 100))
else:
return str(random.randint(1, 20))
ops = ["+", "-", "*"]
op = random.choice(ops)
return f"({expr(depth+1, vars)} {op} {expr(depth+1, vars)})"
def cond(vars=None):
if vars is None:
vars = ["a", "b", "n"]
ops = ["<", ">", "<=", ">=", "==", "!="]
op = random.choice(ops)
lhs = expr(0, vars)
rhs = expr(0, vars)
return f"{lhs} {op} {rhs}"
# ── Fonksiyon gövdesi üreteci ─────────────────────────────────────────────────
def gen_body(fn_idx, local_vars, indent=1):
pad = " " * indent
code = []
# 2-5 lokal değişken tanımı — sadece declare edilenleri ifadelerde kullan
n_vars = random.randint(2, 5)
declared = []
for v in local_vars[:n_vars]:
# İlk değişken sadece sabitle başlatılır (henüz başka değişken yok)
init = expr(0, declared if declared else ["1"])
code.append(f"{pad}int {v} = {init};")
declared.append(v)
local_vars = declared # bundan sonra sadece declare edilenleri kullan
# 1-3 if bloğu
for _ in range(random.randint(1, 3)):
c = cond(local_vars)
then_val = expr(0, local_vars)
code.append(f"{pad}if ({c}) {{")
code.append(f"{pad} {local_vars[0]} = {then_val};")
if random.random() < 0.4:
else_val = expr(0, local_vars)
code.append(f"{pad}}} else {{")
code.append(f"{pad} {local_vars[0]} = {else_val};")
code.append(f"{pad}}}")
# 0-2 for döngüsü
for _ in range(random.randint(0, 2)):
bound = random.randint(3, 15)
inner = expr(0, local_vars)
code.append(f"{pad}for (int i = 0; i < {bound}; i = i + 1) {{")
code.append(f"{pad} {local_vars[0]} = {local_vars[0]} + {inner};")
code.append(f"{pad}}}")
# return
ret_val = expr(0, local_vars)
code.append(f"{pad}return {ret_val};")
return code
# ── Fonksiyon tanımları ───────────────────────────────────────────────────────
# Toplam ~5000 fonksiyon → ~1 MB hedef
FUNC_COUNT = 5000
func_names = [f"fn_{i:04d}" for i in range(FUNC_COUNT)]
func_params = {} # fname → n_params (çağrı sırasında eşleştirmek için)
for i, fname in enumerate(func_names):
# Parametre listesi (0-3 parametre)
n_params = random.randint(0, 3)
func_params[fname] = n_params
params = [f"int p{j}" for j in range(n_params)]
param_str = ", ".join(params)
# Lokal değişken adları
local_vars = ["a", "b", "c", "d", "e",
f"v{i % 10}", f"w{i % 7}"]
emit(f"int {fname}({param_str}) {{")
for line in gen_body(i, local_vars):
emit(line)
emit("}")
emit()
# ── Main ──────────────────────────────────────────────────────────────────────
emit("int main() {")
emit(" int result = 0;")
emit()
# Her 50 fonksiyonu bir kere çağır — argüman sayısı imzayla eşleştirildi
for i in range(0, FUNC_COUNT, 50):
fname = func_names[i]
n_params = func_params[fname]
args = ", ".join(str(random.randint(1, 20)) for _ in range(n_params))
emit(f" result = result + {fname}({args});")
emit()
emit(" print(result);")
emit(" return 0;")
emit("}")
# ── Yaz ───────────────────────────────────────────────────────────────────────
output = "\n".join(lines) + "\n"
path = sys.argv[1] if len(sys.argv) > 1 else "examples/large.sqt"
with open(path, "w", encoding="utf-8") as f:
f.write(output)
size_kb = len(output.encode("utf-8")) / 1024
print(f"Üretildi: {path} ({size_kb:.1f} KB, {len(lines)} satır)")