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})
|
||||
|
||||
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 "symbol/symbol_table.hpp"
|
||||
#include "symbol/symbol_collector.hpp"
|
||||
#include "semantic/type_checker.hpp"
|
||||
#include "semantic/structural_validator.hpp"
|
||||
#include "diagnostic/diagnostic_engine.hpp"
|
||||
#include "ir/ir_generator.hpp"
|
||||
|
||||
|
|
@ -29,6 +31,8 @@ inline int cmdIr(const CliArgs& args) {
|
|||
SymbolTable symbolTable;
|
||||
DiagnosticEngine diag;
|
||||
SymbolCollector(symbolTable, diag).collect(ast);
|
||||
TypeChecker(symbolTable, diag).check(ast);
|
||||
StructuralValidator(diag).validate(ast);
|
||||
|
||||
if (diag.hasErrors()) {
|
||||
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
|
||||
#define SAQUT_VM_VALUE
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
// Gelecekte float/bool/string eklendiğinde burası genişleyecek.
|
||||
// Şimdilik sadece int.
|
||||
// Çalışma zamanı değer tipi.
|
||||
//
|
||||
// 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 {
|
||||
Int,
|
||||
String,
|
||||
// Float, // TODO(vm-genişletme)
|
||||
// Bool, // TODO(vm-genişletme)
|
||||
// Float, // TODO: float literal + aritmetik eklenince
|
||||
};
|
||||
|
||||
struct Value {
|
||||
ValueKind kind = ValueKind::Int;
|
||||
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) {
|
||||
Value v;
|
||||
|
|
@ -47,12 +36,23 @@ struct Value {
|
|||
|
||||
// JIF_FALSE için: int 0 = yanlış, boş string = yanlış, diğer = doğru
|
||||
bool isTruthy() const {
|
||||
if (kind == ValueKind::Int) return intValue != 0;
|
||||
if (kind == ValueKind::String) return !stringValue.empty();
|
||||
switch (kind) {
|
||||
case ValueKind::Int: return intValue != 0;
|
||||
case ValueKind::String: return !stringValue.empty();
|
||||
}
|
||||
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 {
|
||||
switch (kind) {
|
||||
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