test: golden-test koşucusu + Value audit + saqut ir pipeline fix
closes #113, #114, #75 - cmake/run_golden.cmake: BINARY/SOURCE/EXPECTED ile çalışan karşılaştırma betiği - CMakeLists.txt: enable_testing(), golden test otomatik keşif (CONFIGURE_DEPENDS), unit_tests (tests/run.sh) ctest entegrasyonu - tests/golden/: fibonacci, string, arithmetic — 4/4 yeşil (negatif doğrulama da geçti) - value.hpp: stale yorum temizlendi, toString() eklendi, switch exhaustive hale getirildi - ir.hpp: TypeChecker + StructuralValidator eklendi — run pipeline ile artık eşit
This commit is contained in:
parent
d534410874
commit
27a5bc753e
|
|
@ -20,3 +20,38 @@ 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 + .expected çiftlerini otomatik keşfet
|
||||||
|
file(GLOB_RECURSE ALL_GOLDEN_SQT CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_SOURCE_DIR}/tests/golden/*.sqt"
|
||||||
|
)
|
||||||
|
foreach(SQT_FILE ${ALL_GOLDEN_SQT})
|
||||||
|
# Göreli yoldan test adı üret: fibonacci/fib.sqt → golden_fibonacci_fib
|
||||||
|
file(RELATIVE_PATH REL "${CMAKE_SOURCE_DIR}/tests/golden" "${SQT_FILE}")
|
||||||
|
string(REPLACE ".sqt" "" BASE "${REL}")
|
||||||
|
string(REPLACE "/" "_" TNAME "${BASE}")
|
||||||
|
set(EXPECTED_FILE "${CMAKE_SOURCE_DIR}/tests/golden/${BASE}.expected")
|
||||||
|
|
||||||
|
if(EXISTS "${EXPECTED_FILE}")
|
||||||
|
add_test(
|
||||||
|
NAME "golden_${TNAME}"
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-DBINARY=${SAQUT_BINARY}
|
||||||
|
-DSOURCE=${SQT_FILE}
|
||||||
|
-DEXPECTED=${EXPECTED_FILE}
|
||||||
|
-P "${GOLDEN_SCRIPT}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# run_golden.cmake — tek bir golden test çalıştırır ve çıktıyı karşılaştırır.
|
||||||
|
#
|
||||||
|
# Kullanım (CMake add_test içinden):
|
||||||
|
# cmake -DBINARY=<saqut yolu> -DSOURCE=<.sqt yolu> -DEXPECTED=<.expected yolu>
|
||||||
|
# [-DCOMMAND=run] -P run_golden.cmake
|
||||||
|
#
|
||||||
|
# COMMAND varsayılanı "run". IR testleri için COMMAND=ir geçilir.
|
||||||
|
|
||||||
|
if(NOT DEFINED COMMAND)
|
||||||
|
set(COMMAND "run")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${BINARY}" "${COMMAND}" "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()
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#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"
|
||||||
|
|
||||||
|
|
@ -29,6 +31,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);
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,24 @@
|
||||||
// ============================================================================
|
|
||||||
// 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 <stdexcept>
|
||||||
|
|
||||||
// Gelecekte float/bool/string eklendiğinde burası genişleyecek.
|
// Çalışma zamanı değer tipi.
|
||||||
// Şimdilik sadece int.
|
//
|
||||||
|
// Bool ayrı bir kind değil — boolean sonuçlar int olarak saklanır
|
||||||
|
// (0 = yanlış, sıfır-dışı = doğru; C geleneği, JIF_FALSE buna dayanır).
|
||||||
|
// Float henüz implement edilmedi — IR'de float opcode yok.
|
||||||
enum class ValueKind {
|
enum class ValueKind {
|
||||||
Int,
|
Int,
|
||||||
String,
|
String,
|
||||||
// Float, // TODO(vm-genişletme)
|
// Float, // TODO: float literal + aritmetik eklenince
|
||||||
// Bool, // TODO(vm-genişletme)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
std::string stringValue; // yalnızca kind == String için geçerli
|
||||||
|
|
||||||
static Value fromInt(int n) {
|
static Value fromInt(int n) {
|
||||||
Value v;
|
Value v;
|
||||||
|
|
@ -47,12 +36,23 @@ struct Value {
|
||||||
|
|
||||||
// JIF_FALSE için: int 0 = yanlış, boş string = yanlış, diğer = doğru
|
// 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::String: return !stringValue.empty();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okunabilir metin — dump ve hata mesajları için
|
// Yazdırma ve hata mesajları için okunabilir temsil
|
||||||
|
std::string toString() const {
|
||||||
|
switch (kind) {
|
||||||
|
case ValueKind::Int: return std::to_string(intValue);
|
||||||
|
case ValueKind::String: return stringValue;
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tip adı — hata mesajları için
|
||||||
std::string typeName() const {
|
std::string typeName() const {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case ValueKind::Int: return "int";
|
case ValueKind::Int: return "int";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
5
|
||||||
|
6
|
||||||
|
12
|
||||||
|
3
|
||||||
|
1
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
int main() {
|
||||||
|
print(2 + 3);
|
||||||
|
print(10 - 4);
|
||||||
|
print(3 * 4);
|
||||||
|
print(10 / 3);
|
||||||
|
print(10 % 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
55
|
||||||
|
55
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Merhaba
|
||||||
|
saQut calisiyor
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
int main() {
|
||||||
|
print("Merhaba");
|
||||||
|
print("saQut calisiyor");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue