166 lines
5.0 KiB
C
166 lines
5.0 KiB
C
|
|
#include "../lexer/lexer.h"
|
||
|
|
#include "../parser/parser.h"
|
||
|
|
#include "../semantic/semantic.h"
|
||
|
|
#include "../ir/ir.h"
|
||
|
|
#include "../ir/ir_gen.h"
|
||
|
|
#include "../runtime/runtime.h"
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
static int test_count = 0;
|
||
|
|
static int pass_count = 0;
|
||
|
|
|
||
|
|
static void run_test_int(const char* name, const char* source, int expected) {
|
||
|
|
test_count++;
|
||
|
|
|
||
|
|
RavaLexer_t* lexer = rava_lexer_create(source);
|
||
|
|
RavaParser_t* parser = rava_parser_create(lexer);
|
||
|
|
RavaASTNode_t* ast = rava_parser_parse(parser);
|
||
|
|
|
||
|
|
if (!ast || parser->had_error) {
|
||
|
|
printf("FAIL: %s - Parse error: %s\n", name, parser->error_message ? parser->error_message : "unknown");
|
||
|
|
rava_parser_destroy(parser);
|
||
|
|
rava_lexer_destroy(lexer);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaSemanticAnalyzer_t* analyzer = rava_semantic_analyzer_create();
|
||
|
|
rava_semantic_analyze(analyzer, ast);
|
||
|
|
|
||
|
|
RavaIRGenerator_t* ir_gen = rava_ir_generator_create(analyzer);
|
||
|
|
RavaProgram_t* program = rava_ir_generate(ir_gen, ast);
|
||
|
|
|
||
|
|
RavaVM_t* vm = rava_vm_create(program);
|
||
|
|
|
||
|
|
if (!rava_vm_execute(vm, "Test", "main")) {
|
||
|
|
printf("FAIL: %s - Runtime error: %s\n", name, vm->error_message ? vm->error_message : "unknown");
|
||
|
|
rava_vm_destroy(vm);
|
||
|
|
rava_program_destroy(program);
|
||
|
|
rava_ir_generator_destroy(ir_gen);
|
||
|
|
rava_semantic_analyzer_destroy(analyzer);
|
||
|
|
rava_ast_node_destroy(ast);
|
||
|
|
rava_parser_destroy(parser);
|
||
|
|
rava_lexer_destroy(lexer);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaValue_t result = rava_vm_get_result(vm);
|
||
|
|
int32_t result_int = rava_value_as_int(result);
|
||
|
|
|
||
|
|
if (result_int == expected) {
|
||
|
|
printf("PASS: %s (result=%d)\n", name, result_int);
|
||
|
|
pass_count++;
|
||
|
|
} else {
|
||
|
|
printf("FAIL: %s (expected=%d, got=%d)\n", name, expected, result_int);
|
||
|
|
}
|
||
|
|
|
||
|
|
rava_vm_destroy(vm);
|
||
|
|
rava_program_destroy(program);
|
||
|
|
rava_ir_generator_destroy(ir_gen);
|
||
|
|
rava_semantic_analyzer_destroy(analyzer);
|
||
|
|
rava_ast_node_destroy(ast);
|
||
|
|
rava_parser_destroy(parser);
|
||
|
|
rava_lexer_destroy(lexer);
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(void) {
|
||
|
|
printf("=== Short-Circuit Evaluation Tests ===\n\n");
|
||
|
|
|
||
|
|
run_test_int("AND true && true",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (true && true) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 1);
|
||
|
|
|
||
|
|
run_test_int("AND true && false",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (true && false) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 0);
|
||
|
|
|
||
|
|
run_test_int("AND false && true",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (false && true) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 0);
|
||
|
|
|
||
|
|
run_test_int("OR false || true",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (false || true) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 1);
|
||
|
|
|
||
|
|
run_test_int("OR true || false",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (true || false) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 1);
|
||
|
|
|
||
|
|
run_test_int("OR false || false",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (false || false) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 0);
|
||
|
|
|
||
|
|
run_test_int("short-circuit AND skips second",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int x = 0;\n"
|
||
|
|
" public static boolean incAndReturn() {\n"
|
||
|
|
" x = x + 1;\n"
|
||
|
|
" return true;\n"
|
||
|
|
" }\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (false && incAndReturn()) { }\n"
|
||
|
|
" return x;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 0);
|
||
|
|
|
||
|
|
run_test_int("short-circuit OR skips second",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int x = 0;\n"
|
||
|
|
" public static boolean incAndReturn() {\n"
|
||
|
|
" x = x + 1;\n"
|
||
|
|
" return false;\n"
|
||
|
|
" }\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" if (true || incAndReturn()) { }\n"
|
||
|
|
" return x;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 0);
|
||
|
|
|
||
|
|
run_test_int("AND with comparison",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" int x = 5;\n"
|
||
|
|
" if (x > 0 && x < 10) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 1);
|
||
|
|
|
||
|
|
run_test_int("OR with comparison",
|
||
|
|
"public class Test {\n"
|
||
|
|
" public static int main() {\n"
|
||
|
|
" int x = 15;\n"
|
||
|
|
" if (x < 0 || x > 10) { return 1; }\n"
|
||
|
|
" return 0;\n"
|
||
|
|
" }\n"
|
||
|
|
"}\n", 1);
|
||
|
|
|
||
|
|
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
|
||
|
|
|
||
|
|
return (pass_count == test_count) ? 0 : 1;
|
||
|
|
}
|