feat(run): --optimized bayrağı — optimize edilmiş IR üzerinden VM çalıştırma

- run.hpp: args.optimized ise OptimizationManager klonu üretip IR generator'a verir
- ir.hpp + run.hpp: optDiag.printAll sadece gerçek mesaj varsa çağrılıyor (boş özet gürültüsü giderildi)
- tests/golden/opt/run_opt.sqt: constant folding + DCE tetikleyen golden fixture
- run_opt.expected: ham run doğruluk testi (test #9)
- run_opt.run_opt.expected: optimize run doğruluk testi (test #10)
  → "optimizasyon oldu" değil "optimize IR doğru sonuç verdi" regresyon kalkanı
- CMakeLists.txt: *.run_opt.expected → saqut run --optimized otomatik keşif
11/11 ctest geçti
This commit is contained in:
abdussamedulutas 2026-06-18 23:04:57 +03:00
parent 913b42026c
commit ab47e42954
6 changed files with 84 additions and 11 deletions

View File

@ -72,4 +72,19 @@ foreach(SQT_FILE ${ALL_GOLDEN_SQT})
-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()
endforeach()

View File

@ -52,7 +52,8 @@ inline int cmdIr(const CliArgs& args) {
OptimizationManager mgr(cfg, optDiag);
optimizedAst = mgr.optimize(ast, &symbolTable);
activeAst = optimizedAst;
optDiag.printAll(std::cerr); // W002 vb. uyarılar stderr'e
if (optDiag.errorCount() + optDiag.warningCount() > 0)
optDiag.printAll(std::cerr); // W002 vb. uyarılar stderr'e
}
IRGenerator irGenerator;

View File

@ -2,12 +2,11 @@
// saQut CLI — run komutu
//
// 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:
// build/saqut run file:examples/fibonacci.sqt
// → 55
// → 55
// --optimized bayrağı: orijinal AST klonlanır, constant folding + DCE uygulanır,
// optimize edilmiş klon IR generator'a verilir. Orijinal AST dokunulmadan kalır.
// Aynı pattern ir.hpp'de de kullanılıyor — paralel değişikliklerde ikisine bak.
// ============================================================================
#ifndef SAQUT_CLI_RUN
@ -22,6 +21,8 @@
#include "semantic/type_checker.hpp"
#include "semantic/structural_validator.hpp"
#include "diagnostic/diagnostic_engine.hpp"
#include "core/config.hpp"
#include "opt/optimization_manager.hpp"
#include "ir/ir_generator.hpp"
#include "vm/interpreter.hpp"
@ -43,7 +44,7 @@ inline int cmdRun(const CliArgs& args) {
return 1;
}
// ── Aşama 3: Sembol toplama ───────────────────────────────────────────
// ── Aşama 3: Sembol toplama + semantik analiz ─────────────────────────
// Identifier'ların resolvedSymbol'ü doldurulur — IR generator buna ihtiyaç duyar.
SymbolTable symbolTable;
DiagnosticEngine diag;
@ -59,11 +60,27 @@ inline int cmdRun(const CliArgs& args) {
return 1;
}
// ── Aşama 4: IR üretimi ───────────────────────────────────────────────
IRGenerator irGenerator;
IRProgram program = irGenerator.generate(ast, symbolTable);
// ── Aşama 4 (opsiyonel): Optimizasyon ────────────────────────────────
// --optimized bayrağı verilmişse: orijinal AST'yi kopyala, klon üstünde
// constant folding + DCE uygula. IR generator klonu kullanır; orijinal
// bu scope'ta silinir. Bayrak yoksa sıfır maliyet — klonlama olmaz.
ASTNode* activeAst = ast;
ASTNode* optimizedAst = nullptr;
if (args.optimized) {
CompilerConfig cfg;
DiagnosticEngine optDiag;
OptimizationManager mgr(cfg, optDiag);
optimizedAst = mgr.optimize(ast, &symbolTable);
activeAst = optimizedAst;
if (optDiag.errorCount() + optDiag.warningCount() > 0)
optDiag.printAll(std::cerr); // W002 (derleme zamanı sıfıra bölme) vb.
}
// ── Aşama 5: VM çalıştırma ────────────────────────────────────────────
// ── Aşama 5: IR üretimi ───────────────────────────────────────────────
IRGenerator irGenerator;
IRProgram program = irGenerator.generate(activeAst, symbolTable);
// ── Aşama 6: VM çalıştırma ────────────────────────────────────────────
int exitCode = 0;
try {
Interpreter vm(program);
@ -73,6 +90,7 @@ inline int cmdRun(const CliArgs& args) {
exitCode = 1;
}
delete optimizedAst; // nullptr ise no-op; orijinal ast her durumda aşağıda silinir
delete ast;
for (auto* t : tokens) delete t;
return exitCode;

View File

@ -0,0 +1,4 @@
14
1
0
25

View File

@ -0,0 +1,4 @@
14
1
0
25

View File

@ -0,0 +1,31 @@
// Optimize edilmiş çalıştırmanın doğruluğunu kanıtlayan golden test.
//
// Tetiklenen optimizasyonlar:
// - Constant folding: 100 - 6*15 + 4, 3*3 + 4*4 derleme zamanında hesaplanır
// - DCE: return sonrası print(999) ve print(888) silinir
// - Folding zincirleme: iç fonksiyon çağrısı olmaksızın tüm sabit ifadeler katlanır
//
// saqut run ve saqut run --optimized AYNI çıktıyı vermeli.
// Eğer optimizasyon bir değeri yanlış katlarsa veya canlı kodu silerse bu test kırılır.
int compute() {
int result = 100 - 6 * 15 + 4;
return result;
print(999);
}
int classify(int n) {
if (n > 0) {
return 1;
print(888);
}
return 0;
}
int main() {
print(compute());
print(classify(5));
print(classify(-3));
print(3 * 3 + 4 * 4);
return 0;
}