Update.
All checks were successful
CI / Unit Tests (push) Successful in 19s
CI / Optimization Infrastructure Tests (push) Successful in 19s
CI / Integration Tests (push) Successful in 40s
CI / Performance Benchmark (push) Successful in 35s

This commit is contained in:
retoor 2025-12-04 16:55:18 +01:00
parent 1afd91c1c7
commit 0d11a127e2
75 changed files with 5309 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.md
.gitignore
*.swp
merge.py
/test_*
*.o
run_examples

84
tests/test_7_8.c Normal file
View File

@ -0,0 +1,84 @@
#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>
#include <stdbool.h>
static char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
static bool run_example(const char *filename, const char *class_name) {
printf("\n========================================\n");
printf("Running: %s\n", filename);
printf("========================================\n");
char *source = read_file(filename);
if (!source) return false;
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
free(source);
return false;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
free(source);
return false;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
free(source);
return false;
}
RavaVM_t *vm = rava_vm_create(program);
printf("\nOutput:\n");
if (!rava_vm_execute(vm, class_name, "main")) {
printf("\nRuntime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return false;
}
printf("\n✅ Execution completed successfully!\n");
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);
free(source);
return true;
}
int main() {
run_example("examples/07_CollatzConjecture.java", "CollatzConjecture");
run_example("examples/08_PascalTriangle.java", "PascalTriangle");
return 0;
}

110
tests/test_all_10.c Normal file
View File

@ -0,0 +1,110 @@
#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>
#include <stdbool.h>
static char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
static bool run_example(const char *filename, const char *class_name) {
printf("\n========================================\n");
printf("Running: %s\n", filename);
printf("========================================\n");
fflush(stdout);
char *source = read_file(filename);
if (!source) return false;
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
free(source);
return false;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
free(source);
return false;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
free(source);
return false;
}
RavaVM_t *vm = rava_vm_create(program);
printf("\nOutput:\n");
fflush(stdout);
if (!rava_vm_execute(vm, class_name, "main")) {
printf("\nRuntime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return false;
}
printf("\n✅ Execution completed successfully!\n");
fflush(stdout);
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);
free(source);
return true;
}
int main() {
const char *examples[][2] = {
{"examples/01_Fibonacci.java", "Fibonacci"},
{"examples/02_PrimeNumbers.java", "PrimeNumbers"},
{"examples/03_FactorialVariations.java", "FactorialVariations"},
{"examples/04_GCD_LCM.java", "GCD_LCM"},
{"examples/05_PowerFunction.java", "PowerFunction"},
{"examples/06_BubbleSort.java", "BubbleSort"},
{"examples/07_CollatzConjecture.java", "CollatzConjecture"},
{"examples/08_PascalTriangle.java", "PascalTriangle"},
{"examples/09_TowerOfHanoi.java", "TowerOfHanoi"},
{"examples/10_AckermannFunction.java", "AckermannFunction"},
};
int passed = 0;
for (size_t i = 0; i < 10; i++) {
printf("\n[%zu/10]\n", i+1);
fflush(stdout);
if (run_example(examples[i][0], examples[i][1])) {
passed++;
}
}
printf("\n========================================\n");
printf("SUMMARY: %d/10 passed\n", passed);
printf("========================================\n");
return (passed == 10) ? 0 : 1;
}

125
tests/test_array_init.c Normal file
View File

@ -0,0 +1,125 @@
#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("=== Array Initializer Tests ===\n\n");
run_test_int("simple array init",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = {1, 2, 3};\n"
" return arr[0] + arr[1] + arr[2];\n"
" }\n"
"}\n", 6);
run_test_int("array init with expressions",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = {1 + 1, 2 * 2, 3 + 3};\n"
" return arr[0] + arr[1] + arr[2];\n"
" }\n"
"}\n", 12);
run_test_int("single element array",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = {42};\n"
" return arr[0];\n"
" }\n"
"}\n", 42);
run_test_int("array init length",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = {5, 10, 15, 20};\n"
" int sum = 0;\n"
" for (int i = 0; i < 4; i = i + 1) {\n"
" sum = sum + arr[i];\n"
" }\n"
" return sum;\n"
" }\n"
"}\n", 50);
run_test_int("array init with negative values",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = {-1, -2, -3};\n"
" return arr[0] + arr[1] + arr[2];\n"
" }\n"
"}\n", -6);
run_test_int("array init with zero",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = {0, 0, 0};\n"
" return arr[0] + arr[1] + arr[2];\n"
" }\n"
"}\n", 0);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_array_init.o Normal file

Binary file not shown.

30
tests/test_array_syntax.c Normal file
View File

@ -0,0 +1,30 @@
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *source =
"public class ArrayTest {\n"
" public static int main() {\n"
" int[] numbers = new int[5];\n"
" numbers[0] = 10;\n"
" numbers[1] = 20;\n"
" int result = numbers[0] + numbers[1];\n"
" System.out.println(result);\n"
" return 0;\n"
" }\n"
"}\n";
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
return 1;
}
printf("Parsed successfully!\n");
return 0;
}

77
tests/test_arrays.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/11_ArrayOperations.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "ArrayOperations", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

BIN
tests/test_arrays.o Normal file

Binary file not shown.

64
tests/test_benchmark.c Normal file
View File

@ -0,0 +1,64 @@
#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>
static char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/20_Benchmark.java");
if (!source) { printf("Failed to read file\n"); return 1; }
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "Benchmark", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
rava_vm_destroy(vm);
free(source);
return 0;
}

214
tests/test_bitwise.c Normal file
View File

@ -0,0 +1,214 @@
#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("=== Bitwise Operator Tests ===\n\n");
run_test_int("bitwise AND with vars",
"public class Test {\n"
" public static int main() {\n"
" int a = 12;\n"
" int b = 10;\n"
" return a & b;\n"
" }\n"
"}\n", 8);
run_test_int("bitwise OR with vars",
"public class Test {\n"
" public static int main() {\n"
" int a = 12;\n"
" int b = 10;\n"
" return a | b;\n"
" }\n"
"}\n", 14);
run_test_int("bitwise XOR",
"public class Test {\n"
" public static int main() {\n"
" return 12 ^ 10;\n"
" }\n"
"}\n", 6);
run_test_int("left shift",
"public class Test {\n"
" public static int main() {\n"
" return 1 << 4;\n"
" }\n"
"}\n", 16);
run_test_int("right shift",
"public class Test {\n"
" public static int main() {\n"
" return 16 >> 2;\n"
" }\n"
"}\n", 4);
run_test_int("unsigned right shift",
"public class Test {\n"
" public static int main() {\n"
" return 16 >>> 2;\n"
" }\n"
"}\n", 4);
run_test_int("combined bitwise ops",
"public class Test {\n"
" public static int main() {\n"
" int a = 5;\n"
" int b = 3;\n"
" return (a & b) | (a ^ b);\n"
" }\n"
"}\n", 7);
run_test_int("shift with variable",
"public class Test {\n"
" public static int main() {\n"
" int x = 2;\n"
" return 1 << x;\n"
" }\n"
"}\n", 4);
run_test_int("bitwise mask",
"public class Test {\n"
" public static int main() {\n"
" int value = 255;\n"
" int mask = 0x0F;\n"
" return value & mask;\n"
" }\n"
"}\n", 15);
run_test_int("bit toggle with XOR",
"public class Test {\n"
" public static int main() {\n"
" int flags = 5;\n"
" return flags ^ 1;\n"
" }\n"
"}\n", 4);
run_test_int("bitwise NOT",
"public class Test {\n"
" public static int main() {\n"
" int x = 0;\n"
" return ~x;\n"
" }\n"
"}\n", -1);
run_test_int("bitwise NOT with value",
"public class Test {\n"
" public static int main() {\n"
" int x = 5;\n"
" return ~x;\n"
" }\n"
"}\n", -6);
run_test_int("compound AND assign",
"public class Test {\n"
" public static int main() {\n"
" int x = 15;\n"
" x &= 7;\n"
" return x;\n"
" }\n"
"}\n", 7);
run_test_int("compound OR assign",
"public class Test {\n"
" public static int main() {\n"
" int x = 8;\n"
" x |= 3;\n"
" return x;\n"
" }\n"
"}\n", 11);
run_test_int("compound XOR assign",
"public class Test {\n"
" public static int main() {\n"
" int x = 12;\n"
" x ^= 5;\n"
" return x;\n"
" }\n"
"}\n", 9);
run_test_int("compound left shift assign",
"public class Test {\n"
" public static int main() {\n"
" int x = 1;\n"
" x <<= 3;\n"
" return x;\n"
" }\n"
"}\n", 8);
run_test_int("compound right shift assign",
"public class Test {\n"
" public static int main() {\n"
" int x = 16;\n"
" x >>= 2;\n"
" return x;\n"
" }\n"
"}\n", 4);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_bitwise.o Normal file

Binary file not shown.

42
tests/test_break.c Normal file
View File

@ -0,0 +1,42 @@
#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>
static char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/19_BreakContinue.java");
if (!source) { printf("Failed\n"); return 1; }
RavaLexer_t *l = rava_lexer_create(source);
RavaParser_t *p = rava_parser_create(l);
RavaASTNode_t *ast = rava_parser_parse(p);
if (p->had_error) { printf("Parse: %s\n", p->error_message); return 1; }
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *a = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(a, ast)) { printf("Semantic: %s\n", a->error_message); return 1; }
printf("Semantic: OK\n");
RavaIRGenerator_t *g = rava_ir_generator_create(a);
RavaProgram_t *prog = rava_ir_generate(g, ast);
if (!prog) { printf("IR failed\n"); return 1; }
printf("IR: OK\nOutput:\n");
RavaVM_t *vm = rava_vm_create(prog);
if (!rava_vm_execute(vm, "BreakContinue", "main")) { printf("Runtime: %s\n", vm->error_message); return 1; }
printf("\nExecution: OK\n");
return 0;
}

278
tests/test_collections.c Normal file
View File

@ -0,0 +1,278 @@
#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 int run_test(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 (parser->had_error) {
printf("FAIL: %s (parse error)\n", name);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return 0;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("FAIL: %s (semantic error)\n", name);
rava_semantic_analyzer_destroy(analyzer);
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return 0;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("FAIL: %s (IR error)\n", name);
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 0;
}
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "Test", "main")) {
printf("FAIL: %s (runtime error)\n", name);
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 0;
}
RavaValue_t result = rava_vm_get_result(vm);
int actual = rava_value_as_int(result);
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);
if (actual == expected) {
printf("PASS: %s\n", name);
pass_count++;
return 1;
} else {
printf("FAIL: %s (expected %d, got %d)\n", name, expected, actual);
return 0;
}
}
int main(void) {
printf("=== ArrayList Tests ===\n");
run_test("ArrayList create and size",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" return list.size();\n"
" }\n"
"}\n", 0);
run_test("ArrayList add and size",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(10);\n"
" list.add(20);\n"
" list.add(30);\n"
" return list.size();\n"
" }\n"
"}\n", 3);
run_test("ArrayList add and get",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(42);\n"
" return list.get(0);\n"
" }\n"
"}\n", 42);
run_test("ArrayList set",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(10);\n"
" list.set(0, 99);\n"
" return list.get(0);\n"
" }\n"
"}\n", 99);
run_test("ArrayList isEmpty true",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" if (list.isEmpty()) {\n"
" return 1;\n"
" }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test("ArrayList isEmpty false",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(1);\n"
" if (list.isEmpty()) {\n"
" return 1;\n"
" }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test("ArrayList clear",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(1);\n"
" list.add(2);\n"
" list.clear();\n"
" return list.size();\n"
" }\n"
"}\n", 0);
run_test("ArrayList remove",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(10);\n"
" list.add(20);\n"
" list.add(30);\n"
" int removed = list.remove(1);\n"
" return removed;\n"
" }\n"
"}\n", 20);
run_test("ArrayList sum elements",
"public class Test {\n"
" public static int main() {\n"
" ArrayList list = new ArrayList();\n"
" list.add(1);\n"
" list.add(2);\n"
" list.add(3);\n"
" list.add(4);\n"
" int sum = 0;\n"
" for (int i = 0; i < list.size(); i = i + 1) {\n"
" sum = sum + list.get(i);\n"
" }\n"
" return sum;\n"
" }\n"
"}\n", 10);
printf("\n=== HashMap Tests ===\n");
run_test("HashMap create and size",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" return map.size();\n"
" }\n"
"}\n", 0);
run_test("HashMap put and size",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"a\", 1);\n"
" map.put(\"b\", 2);\n"
" return map.size();\n"
" }\n"
"}\n", 2);
run_test("HashMap put and get",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"key\", 42);\n"
" return map.get(\"key\");\n"
" }\n"
"}\n", 42);
run_test("HashMap containsKey true",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"test\", 99);\n"
" if (map.containsKey(\"test\")) {\n"
" return 1;\n"
" }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test("HashMap containsKey false",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"test\", 99);\n"
" if (map.containsKey(\"other\")) {\n"
" return 1;\n"
" }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test("HashMap remove",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"a\", 10);\n"
" map.put(\"b\", 20);\n"
" int removed = map.remove(\"a\");\n"
" return removed + map.size();\n"
" }\n"
"}\n", 11);
run_test("HashMap clear",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"x\", 1);\n"
" map.put(\"y\", 2);\n"
" map.clear();\n"
" return map.size();\n"
" }\n"
"}\n", 0);
run_test("HashMap update value",
"public class Test {\n"
" public static int main() {\n"
" HashMap map = new HashMap();\n"
" map.put(\"key\", 10);\n"
" map.put(\"key\", 20);\n"
" return map.get(\"key\");\n"
" }\n"
"}\n", 20);
printf("\n=== Results ===\n");
printf("Passed: %d/%d\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_collections.o Normal file

Binary file not shown.

139
tests/test_dowhile.c Normal file
View File

@ -0,0 +1,139 @@
#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(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\n", name);
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\n", name);
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("=== Do-While Loop Tests ===\n\n");
run_test("Simple do-while",
"public class Test {\n"
" public static int main() {\n"
" int i = 0;\n"
" do {\n"
" i = i + 1;\n"
" } while (i < 5);\n"
" return i;\n"
" }\n"
"}\n", 5);
run_test("Do-while sum",
"public class Test {\n"
" public static int main() {\n"
" int sum = 0;\n"
" int i = 1;\n"
" do {\n"
" sum = sum + i;\n"
" i = i + 1;\n"
" } while (i <= 10);\n"
" return sum;\n"
" }\n"
"}\n", 55);
run_test("Do-while executes at least once",
"public class Test {\n"
" public static int main() {\n"
" int x = 0;\n"
" do {\n"
" x = 42;\n"
" } while (false);\n"
" return x;\n"
" }\n"
"}\n", 42);
run_test("Do-while with break",
"public class Test {\n"
" public static int main() {\n"
" int i = 0;\n"
" do {\n"
" i = i + 1;\n"
" if (i == 3) {\n"
" break;\n"
" }\n"
" } while (i < 10);\n"
" return i;\n"
" }\n"
"}\n", 3);
run_test("Nested do-while",
"public class Test {\n"
" public static int main() {\n"
" int count = 0;\n"
" int i = 0;\n"
" do {\n"
" int j = 0;\n"
" do {\n"
" count = count + 1;\n"
" j = j + 1;\n"
" } while (j < 3);\n"
" i = i + 1;\n"
" } while (i < 2);\n"
" return count;\n"
" }\n"
"}\n", 6);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_dowhile.o Normal file

Binary file not shown.

77
tests/test_elseif.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/18_ElseIf.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "ElseIf", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

130
tests/test_enhanced_for.c Normal file
View File

@ -0,0 +1,130 @@
#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("=== Enhanced For Loop Tests ===\n\n");
run_test_int("sum array elements",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = new int[3];\n"
" arr[0] = 1;\n"
" arr[1] = 2;\n"
" arr[2] = 3;\n"
" int sum = 0;\n"
" for (int x : arr) {\n"
" sum = sum + x;\n"
" }\n"
" return sum;\n"
" }\n"
"}\n", 6);
run_test_int("count elements",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = new int[5];\n"
" int count = 0;\n"
" for (int x : arr) {\n"
" count = count + 1;\n"
" }\n"
" return count;\n"
" }\n"
"}\n", 5);
run_test_int("find max",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = new int[4];\n"
" arr[0] = 5;\n"
" arr[1] = 9;\n"
" arr[2] = 3;\n"
" arr[3] = 7;\n"
" int max = 0;\n"
" for (int x : arr) {\n"
" if (x > max) {\n"
" max = x;\n"
" }\n"
" }\n"
" return max;\n"
" }\n"
"}\n", 9);
run_test_int("empty array",
"public class Test {\n"
" public static int main() {\n"
" int[] arr = new int[0];\n"
" int sum = 0;\n"
" for (int x : arr) {\n"
" sum = sum + 1;\n"
" }\n"
" return sum;\n"
" }\n"
"}\n", 0);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_enhanced_for.o Normal file

Binary file not shown.

152
tests/test_enums.c Normal file
View File

@ -0,0 +1,152 @@
#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>
static int run_test(const char *name, const char *source, const char *class_name,
const char *method_name, int expected) {
printf("Test: %-40s ... ", name);
fflush(stdout);
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("FAIL (parse error: %s)\n", parser->error_message);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return 0;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("FAIL (semantic error: %s)\n", analyzer->error_message);
rava_semantic_analyzer_destroy(analyzer);
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return 0;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("FAIL (IR generation failed)\n");
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 0;
}
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, class_name, method_name)) {
printf("FAIL (runtime error: %s)\n", 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 0;
}
RavaValue_t result = rava_vm_get_result(vm);
int result_int = rava_value_as_int(result);
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);
if (result_int == expected) {
printf("PASS (result=%d)\n", result_int);
return 1;
} else {
printf("FAIL (expected=%d, got=%d)\n", expected, result_int);
return 0;
}
}
int main(void) {
printf("=== Enum Tests ===\n\n");
int passed = 0;
int total = 0;
total++;
passed += run_test("simple enum ordinal",
"public enum Color { RED, GREEN, BLUE }\n"
"public class Test {\n"
" public static int main() {\n"
" return Color.RED;\n"
" }\n"
"}\n",
"Test", "main", 0);
total++;
passed += run_test("enum second value",
"public enum Color { RED, GREEN, BLUE }\n"
"public class Test {\n"
" public static int main() {\n"
" return Color.GREEN;\n"
" }\n"
"}\n",
"Test", "main", 1);
total++;
passed += run_test("enum third value",
"public enum Color { RED, GREEN, BLUE }\n"
"public class Test {\n"
" public static int main() {\n"
" return Color.BLUE;\n"
" }\n"
"}\n",
"Test", "main", 2);
total++;
passed += run_test("enum comparison",
"public enum Day { MON, TUE, WED, THU, FRI }\n"
"public class Test {\n"
" public static int main() {\n"
" int day = Day.WED;\n"
" if (day == 2) {\n"
" return 42;\n"
" }\n"
" return 0;\n"
" }\n"
"}\n",
"Test", "main", 42);
total++;
passed += run_test("enum in switch",
"public enum Status { OK, ERROR, PENDING }\n"
"public class Test {\n"
" public static int main() {\n"
" int s = Status.ERROR;\n"
" switch (s) {\n"
" case 0: return 10;\n"
" case 1: return 20;\n"
" case 2: return 30;\n"
" default: return 0;\n"
" }\n"
" }\n"
"}\n",
"Test", "main", 20);
printf("\n=== Results: %d/%d tests passed ===\n", passed, total);
return (passed == total) ? 0 : 1;
}

BIN
tests/test_enums.o Normal file

Binary file not shown.

127
tests/test_exceptions.c Normal file
View File

@ -0,0 +1,127 @@
#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("=== Exception Handling Tests ===\n\n");
run_test_int("basic try-catch",
"public class Test {\n"
" public static int main() {\n"
" int result = 0;\n"
" try {\n"
" throw 42;\n"
" } catch (Exception e) {\n"
" result = e;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 42);
run_test_int("try without exception",
"public class Test {\n"
" public static int main() {\n"
" int result = 10;\n"
" try {\n"
" result = 20;\n"
" } catch (Exception e) {\n"
" result = 99;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 20);
run_test_int("catch modifies value",
"public class Test {\n"
" public static int main() {\n"
" int x = 5;\n"
" try {\n"
" throw 10;\n"
" } catch (Exception e) {\n"
" x = x + e;\n"
" }\n"
" return x;\n"
" }\n"
"}\n", 15);
run_test_int("try-finally without exception",
"public class Test {\n"
" public static int main() {\n"
" int result = 0;\n"
" try {\n"
" result = 10;\n"
" } catch (Exception e) {\n"
" result = 99;\n"
" } finally {\n"
" result = result + 5;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 15);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_exceptions.o Normal file

Binary file not shown.

142
tests/test_fastframe.c Normal file
View File

@ -0,0 +1,142 @@
#include <stdio.h>
#include <assert.h>
#include "../runtime/fastframe.h"
static int tests_passed = 0;
#define TEST(name) static void test_##name(void)
#define RUN_TEST(name) do { \
printf("Running %s... ", #name); \
test_##name(); \
printf("PASSED\n"); \
tests_passed++; \
} while(0)
TEST(init) {
rava_fastframe_init();
assert(rava_fastframe_get_depth() == 0);
assert(rava_fastframe_current() == NULL);
}
TEST(push_pop) {
rava_fastframe_init();
FastFrame_t* frame = rava_fastframe_push(NULL, 4);
assert(frame != NULL);
assert(rava_fastframe_get_depth() == 1);
assert(rava_fastframe_current() == frame);
rava_fastframe_pop();
assert(rava_fastframe_get_depth() == 0);
assert(rava_fastframe_current() == NULL);
}
TEST(nested_frames) {
rava_fastframe_init();
FastFrame_t* f1 = rava_fastframe_push(NULL, 2);
FastFrame_t* f2 = rava_fastframe_push(NULL, 2);
FastFrame_t* f3 = rava_fastframe_push(NULL, 2);
assert(rava_fastframe_get_depth() == 3);
assert(rava_fastframe_current() == f3);
rava_fastframe_pop();
assert(rava_fastframe_current() == f2);
rava_fastframe_pop();
assert(rava_fastframe_current() == f1);
rava_fastframe_pop();
assert(rava_fastframe_current() == NULL);
}
TEST(stack_operations) {
rava_fastframe_init();
FastFrame_t* frame = rava_fastframe_push(NULL, 4);
assert(rava_fastframe_stack_is_empty(frame));
rava_fastframe_stack_push(frame, rava_nanbox_int(10));
rava_fastframe_stack_push(frame, rava_nanbox_int(20));
rava_fastframe_stack_push(frame, rava_nanbox_int(30));
assert(!rava_fastframe_stack_is_empty(frame));
assert(frame->stack_top == 3);
RavaNanboxValue_t top = rava_fastframe_stack_peek(frame);
assert(rava_nanbox_as_int(top) == 30);
assert(frame->stack_top == 3);
RavaNanboxValue_t v1 = rava_fastframe_stack_pop(frame);
RavaNanboxValue_t v2 = rava_fastframe_stack_pop(frame);
RavaNanboxValue_t v3 = rava_fastframe_stack_pop(frame);
assert(rava_nanbox_as_int(v1) == 30);
assert(rava_nanbox_as_int(v2) == 20);
assert(rava_nanbox_as_int(v3) == 10);
assert(rava_fastframe_stack_is_empty(frame));
rava_fastframe_reset();
}
TEST(locals) {
rava_fastframe_init();
FastFrame_t* frame = rava_fastframe_push(NULL, 8);
frame->locals[0] = rava_nanbox_int(100);
frame->locals[1] = rava_nanbox_int(200);
frame->locals[2] = rava_nanbox_bool(true);
assert(rava_nanbox_as_int(frame->locals[0]) == 100);
assert(rava_nanbox_as_int(frame->locals[1]) == 200);
assert(rava_nanbox_as_bool(frame->locals[2]) == true);
rava_fastframe_reset();
}
TEST(reset) {
rava_fastframe_init();
rava_fastframe_push(NULL, 2);
rava_fastframe_push(NULL, 2);
rava_fastframe_push(NULL, 2);
assert(rava_fastframe_get_depth() == 3);
rava_fastframe_reset();
assert(rava_fastframe_get_depth() == 0);
}
TEST(stack_clear) {
rava_fastframe_init();
FastFrame_t* frame = rava_fastframe_push(NULL, 4);
rava_fastframe_stack_push(frame, rava_nanbox_int(1));
rava_fastframe_stack_push(frame, rava_nanbox_int(2));
rava_fastframe_stack_push(frame, rava_nanbox_int(3));
assert(frame->stack_top == 3);
rava_fastframe_stack_clear(frame);
assert(frame->stack_top == 0);
assert(rava_fastframe_stack_is_empty(frame));
rava_fastframe_reset();
}
int main(void) {
printf("=== Fast Frame Unit Tests ===\n\n");
RUN_TEST(init);
RUN_TEST(push_pop);
RUN_TEST(nested_frames);
RUN_TEST(stack_operations);
RUN_TEST(locals);
RUN_TEST(reset);
RUN_TEST(stack_clear);
printf("\n=== Results: %d tests passed ===\n", tests_passed);
return 0;
}

77
tests/test_fileio.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/15_FileIO.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "FileIO", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

BIN
tests/test_fileio.o Normal file

Binary file not shown.

77
tests/test_forloop.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/16_ForLoop.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "ForLoop", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

77
tests/test_inheritance.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/17_Inheritance.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "Inheritance", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/14_InstanceMethods.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "InstanceMethods", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

Binary file not shown.

105
tests/test_instanceof.c Normal file
View File

@ -0,0 +1,105 @@
#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("=== Instanceof Tests ===\n\n");
run_test_int("instanceof true",
"public class Animal {}\n"
"public class Test {\n"
" public static int main() {\n"
" Animal a = new Animal();\n"
" if (a instanceof Animal) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("instanceof false",
"public class Animal {}\n"
"public class Dog {}\n"
"public class Test {\n"
" public static int main() {\n"
" Dog d = new Dog();\n"
" if (d instanceof Animal) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test_int("instanceof in expression",
"public class Person {}\n"
"public class Test {\n"
" public static int main() {\n"
" Person p = new Person();\n"
" int result = 0;\n"
" if (p instanceof Person) { result = 42; }\n"
" return result;\n"
" }\n"
"}\n", 42);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_instanceof.o Normal file

Binary file not shown.

148
tests/test_interfaces.c Normal file
View File

@ -0,0 +1,148 @@
#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("=== Interface Tests ===\n\n");
run_test_int("interface with implementing class",
"interface Addable {\n"
" int add(int a, int b);\n"
"}\n"
"class Calculator implements Addable {\n"
" int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Calculator calc = new Calculator();\n"
" return calc.add(10, 20);\n"
" }\n"
"}\n", 30);
run_test_int("class implements multiple interfaces",
"interface Addable {\n"
" int add(int a, int b);\n"
"}\n"
"interface Subtractable {\n"
" int subtract(int a, int b);\n"
"}\n"
"class Calculator implements Addable, Subtractable {\n"
" int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
" int subtract(int a, int b) {\n"
" return a - b;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Calculator calc = new Calculator();\n"
" return calc.add(100, 50) - calc.subtract(30, 10);\n"
" }\n"
"}\n", 130);
run_test_int("class extends and implements",
"interface Printable {\n"
" int getValue();\n"
"}\n"
"class Base {\n"
" int baseValue;\n"
" Base() {\n"
" this.baseValue = 100;\n"
" }\n"
"}\n"
"class Derived extends Base implements Printable {\n"
" int getValue() {\n"
" return this.baseValue + 50;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Derived d = new Derived();\n"
" return d.getValue();\n"
" }\n"
"}\n", 150);
run_test_int("empty interface",
"interface Empty {\n"
"}\n"
"class MyClass implements Empty {\n"
" int getValue() {\n"
" return 42;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" MyClass obj = new MyClass();\n"
" return obj.getValue();\n"
" }\n"
"}\n", 42);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_interfaces.o Normal file

Binary file not shown.

66
tests/test_ir.c Normal file
View File

@ -0,0 +1,66 @@
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include "../semantic/semantic.h"
#include "../ir/ir.h"
#include "../ir/ir_gen.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *source =
"public class Math {\n"
" public static int add(int a, int b) {\n"
" int result = a + b;\n"
" return result;\n"
" }\n"
"\n"
" public static int factorial(int n) {\n"
" if (n <= 1) {\n"
" return 1;\n"
" }\n"
" return n * factorial(n - 1);\n"
" }\n"
"}\n";
printf("Source code:\n%s\n", source);
printf("\nIR Generation:\n");
printf("================================================================================\n\n");
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message ? parser->error_message : "Unknown error");
return 1;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
bool semantic_ok = rava_semantic_analyze(analyzer, ast);
if (!semantic_ok) {
printf("Semantic error: %s\n", analyzer->error_message ? analyzer->error_message : "Unknown error");
return 1;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (program) {
rava_ir_print(program);
printf("\n✓ IR generation completed successfully!\n");
} else {
printf("✗ IR generation failed!\n");
return 1;
}
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);
printf("\nIR test completed!\n");
return 0;
}

BIN
tests/test_ir.o Normal file

Binary file not shown.

124
tests/test_labeltable.c Normal file
View File

@ -0,0 +1,124 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "../ir/ir.h"
#include "../runtime/labeltable.h"
static int tests_passed = 0;
#define TEST(name) static void test_##name(void)
#define RUN_TEST(name) do { \
printf("Running %s... ", #name); \
test_##name(); \
printf("PASSED\n"); \
tests_passed++; \
} while(0)
TEST(create_empty) {
RavaInstructionList_t* list = rava_instruction_list_create();
LabelTable_t* table = rava_labeltable_create(list);
assert(table != NULL);
rava_labeltable_destroy(table);
rava_instruction_list_destroy(list);
}
TEST(create_null) {
LabelTable_t* table = rava_labeltable_create(NULL);
assert(table == NULL);
}
TEST(single_label) {
RavaInstructionList_t* list = rava_instruction_list_create();
RavaInstruction_t instr1 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 10};
RavaInstruction_t instr2 = {.opcode = RAVA_OP_LABEL, .operand.label_id = 0};
RavaInstruction_t instr3 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 20};
rava_instruction_list_add(list, instr1);
rava_instruction_list_add(list, instr2);
rava_instruction_list_add(list, instr3);
LabelTable_t* table = rava_labeltable_create(list);
assert(table != NULL);
size_t pc = rava_labeltable_lookup(table, 0);
assert(pc == 2);
rava_labeltable_destroy(table);
rava_instruction_list_destroy(list);
}
TEST(multiple_labels) {
RavaInstructionList_t* list = rava_instruction_list_create();
RavaInstruction_t instr0 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 0};
RavaInstruction_t label0 = {.opcode = RAVA_OP_LABEL, .operand.label_id = 0};
RavaInstruction_t instr1 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 1};
RavaInstruction_t label1 = {.opcode = RAVA_OP_LABEL, .operand.label_id = 1};
RavaInstruction_t instr2 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 2};
RavaInstruction_t label2 = {.opcode = RAVA_OP_LABEL, .operand.label_id = 2};
rava_instruction_list_add(list, instr0);
rava_instruction_list_add(list, label0);
rava_instruction_list_add(list, instr1);
rava_instruction_list_add(list, label1);
rava_instruction_list_add(list, instr2);
rava_instruction_list_add(list, label2);
LabelTable_t* table = rava_labeltable_create(list);
assert(table != NULL);
assert(rava_labeltable_lookup(table, 0) == 2);
assert(rava_labeltable_lookup(table, 1) == 4);
assert(rava_labeltable_lookup(table, 2) == 6);
rava_labeltable_destroy(table);
rava_instruction_list_destroy(list);
}
TEST(missing_label) {
RavaInstructionList_t* list = rava_instruction_list_create();
RavaInstruction_t label = {.opcode = RAVA_OP_LABEL, .operand.label_id = 5};
rava_instruction_list_add(list, label);
LabelTable_t* table = rava_labeltable_create(list);
assert(table != NULL);
assert(rava_labeltable_lookup(table, 0) == 0);
assert(rava_labeltable_lookup(table, 1) == 0);
assert(rava_labeltable_lookup(table, 5) == 1);
rava_labeltable_destroy(table);
rava_instruction_list_destroy(list);
}
TEST(out_of_range) {
RavaInstructionList_t* list = rava_instruction_list_create();
RavaInstruction_t label = {.opcode = RAVA_OP_LABEL, .operand.label_id = 2};
rava_instruction_list_add(list, label);
LabelTable_t* table = rava_labeltable_create(list);
assert(table != NULL);
assert(rava_labeltable_lookup(table, 100) == 0);
assert(rava_labeltable_lookup(table, -1) == 0);
rava_labeltable_destroy(table);
rava_instruction_list_destroy(list);
}
int main(void) {
printf("=== Label Table Unit Tests ===\n\n");
RUN_TEST(create_empty);
RUN_TEST(create_null);
RUN_TEST(single_label);
RUN_TEST(multiple_labels);
RUN_TEST(missing_label);
RUN_TEST(out_of_range);
printf("\n=== Results: %d tests passed ===\n", tests_passed);
return 0;
}

95
tests/test_lexer.c Normal file
View File

@ -0,0 +1,95 @@
#include "../lexer/lexer.h"
#include <stdio.h>
#include <stdlib.h>
static const char* token_type_to_string(RavaTokenType_e type) {
switch (type) {
case RAVA_TOKEN_EOF: return "EOF";
case RAVA_TOKEN_KEYWORD_CLASS: return "KEYWORD_CLASS";
case RAVA_TOKEN_KEYWORD_PUBLIC: return "KEYWORD_PUBLIC";
case RAVA_TOKEN_KEYWORD_STATIC: return "KEYWORD_STATIC";
case RAVA_TOKEN_KEYWORD_VOID: return "KEYWORD_VOID";
case RAVA_TOKEN_KEYWORD_INT: return "KEYWORD_INT";
case RAVA_TOKEN_KEYWORD_RETURN: return "KEYWORD_RETURN";
case RAVA_TOKEN_KEYWORD_IF: return "KEYWORD_IF";
case RAVA_TOKEN_KEYWORD_ELSE: return "KEYWORD_ELSE";
case RAVA_TOKEN_IDENTIFIER: return "IDENTIFIER";
case RAVA_TOKEN_LITERAL_INTEGER: return "LITERAL_INTEGER";
case RAVA_TOKEN_LITERAL_STRING: return "LITERAL_STRING";
case RAVA_TOKEN_LITERAL_TRUE: return "LITERAL_TRUE";
case RAVA_TOKEN_LITERAL_FALSE: return "LITERAL_FALSE";
case RAVA_TOKEN_LITERAL_NULL: return "LITERAL_NULL";
case RAVA_TOKEN_LPAREN: return "LPAREN";
case RAVA_TOKEN_RPAREN: return "RPAREN";
case RAVA_TOKEN_LBRACE: return "LBRACE";
case RAVA_TOKEN_RBRACE: return "RBRACE";
case RAVA_TOKEN_SEMICOLON: return "SEMICOLON";
case RAVA_TOKEN_COMMA: return "COMMA";
case RAVA_TOKEN_DOT: return "DOT";
case RAVA_TOKEN_ASSIGN: return "ASSIGN";
case RAVA_TOKEN_PLUS: return "PLUS";
case RAVA_TOKEN_MINUS: return "MINUS";
case RAVA_TOKEN_STAR: return "STAR";
case RAVA_TOKEN_EQUAL: return "EQUAL";
case RAVA_TOKEN_LT: return "LT";
case RAVA_TOKEN_GT: return "GT";
case RAVA_TOKEN_ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
int main() {
const char *source =
"public class HelloWorld {\n"
" public static void main(String[] args) {\n"
" int x = 42;\n"
" if (x > 0) {\n"
" System.out.println(\"Hello, World!\");\n"
" }\n"
" return;\n"
" }\n"
"}\n";
printf("Source code:\n%s\n", source);
printf("\nTokens:\n");
printf("%-20s %-30s %s\n", "Type", "Lexeme", "Location");
printf("--------------------------------------------------------------------------------\n");
RavaLexer_t *lexer = rava_lexer_create(source);
RavaToken_t *token;
do {
token = rava_lexer_next_token(lexer);
if (token->type == RAVA_TOKEN_ERROR) {
printf("ERROR: %s at line %d, column %d\n",
lexer->error_message ? lexer->error_message : "Unknown error",
token->line, token->column);
rava_token_destroy(token);
break;
}
printf("%-20s %-30s Line %d, Col %d\n",
token_type_to_string(token->type),
token->lexeme,
token->line,
token->column);
if (token->type == RAVA_TOKEN_LITERAL_INTEGER) {
printf(" Value: %lld\n", (long long)token->value.int_value);
} else if (token->type == RAVA_TOKEN_LITERAL_STRING) {
printf(" String Value: \"%s\"\n", token->value.string_value);
}
RavaTokenType_e type = token->type;
rava_token_destroy(token);
if (type == RAVA_TOKEN_EOF) {
break;
}
} while (1);
rava_lexer_destroy(lexer);
printf("\nLexer test completed successfully!\n");
return 0;
}

BIN
tests/test_lexer.o Normal file

Binary file not shown.

166
tests/test_math.c Normal file
View File

@ -0,0 +1,166 @@
#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>
#include <math.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("=== Math Class Tests ===\n\n");
run_test_int("Math.abs positive",
"public class Test {\n"
" public static int main() {\n"
" return Math.abs(42);\n"
" }\n"
"}\n", 42);
run_test_int("Math.abs negative",
"public class Test {\n"
" public static int main() {\n"
" return Math.abs(-42);\n"
" }\n"
"}\n", 42);
run_test_int("Math.min",
"public class Test {\n"
" public static int main() {\n"
" return Math.min(10, 5);\n"
" }\n"
"}\n", 5);
run_test_int("Math.max",
"public class Test {\n"
" public static int main() {\n"
" return Math.max(10, 5);\n"
" }\n"
"}\n", 10);
run_test_int("(int)Math.pow 2^8",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)Math.pow(2, 8);\n"
" return result;\n"
" }\n"
"}\n", 256);
run_test_int("(int)Math.sqrt 25",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)Math.sqrt(25);\n"
" return result;\n"
" }\n"
"}\n", 5);
run_test_int("(int)Math.floor 4.9",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)Math.floor(4.9);\n"
" return result;\n"
" }\n"
"}\n", 4);
run_test_int("(int)Math.ceil 4.1",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)Math.ceil(4.1);\n"
" return result;\n"
" }\n"
"}\n", 5);
run_test_int("(int)Math.round 4.7",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)Math.round(4.7);\n"
" return result;\n"
" }\n"
"}\n", 5);
run_test_int("(int)Math.round 4.2",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)Math.round(4.2);\n"
" return result;\n"
" }\n"
"}\n", 4);
run_test_int("(int) double cast",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)3.14159;\n"
" return result;\n"
" }\n"
"}\n", 3);
run_test_int("(int) negative double",
"public class Test {\n"
" public static int main() {\n"
" int result = (int)(-7.8);\n"
" return result;\n"
" }\n"
"}\n", -7);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_math.o Normal file

Binary file not shown.

119
tests/test_methodcache.c Normal file
View File

@ -0,0 +1,119 @@
#include <stdio.h>
#include <assert.h>
#include "../runtime/methodcache.h"
static int tests_passed = 0;
#define TEST(name) static void test_##name(void)
#define RUN_TEST(name) do { \
printf("Running %s... ", #name); \
test_##name(); \
printf("PASSED\n"); \
tests_passed++; \
} while(0)
TEST(create_destroy) {
MethodCache_t* cache = rava_methodcache_create();
assert(cache != NULL);
rava_methodcache_destroy(cache);
}
TEST(insert_lookup) {
MethodCache_t* cache = rava_methodcache_create();
assert(cache != NULL);
int dummy_method = 42;
RavaMethod_t* method = (RavaMethod_t*)&dummy_method;
rava_methodcache_insert(cache, "TestClass", "testMethod", method);
RavaMethod_t* found = rava_methodcache_lookup(cache, "TestClass", "testMethod");
assert(found == method);
rava_methodcache_destroy(cache);
}
TEST(lookup_miss) {
MethodCache_t* cache = rava_methodcache_create();
assert(cache != NULL);
RavaMethod_t* found = rava_methodcache_lookup(cache, "NonExistent", "method");
assert(found == NULL);
rava_methodcache_destroy(cache);
}
TEST(multiple_methods) {
MethodCache_t* cache = rava_methodcache_create();
assert(cache != NULL);
int m1 = 1, m2 = 2;
RavaMethod_t* method1 = (RavaMethod_t*)&m1;
RavaMethod_t* method2 = (RavaMethod_t*)&m2;
rava_methodcache_insert(cache, "TestClass", "methodA", method1);
RavaMethod_t* found1 = rava_methodcache_lookup(cache, "TestClass", "methodA");
assert(found1 == method1);
rava_methodcache_insert(cache, "OtherClass", "methodB", method2);
RavaMethod_t* found2 = rava_methodcache_lookup(cache, "OtherClass", "methodB");
assert(found2 == method2);
rava_methodcache_destroy(cache);
}
TEST(clear) {
MethodCache_t* cache = rava_methodcache_create();
assert(cache != NULL);
int dummy = 42;
RavaMethod_t* method = (RavaMethod_t*)&dummy;
rava_methodcache_insert(cache, "TestClass", "testMethod", method);
assert(rava_methodcache_lookup(cache, "TestClass", "testMethod") == method);
rava_methodcache_clear(cache);
assert(rava_methodcache_lookup(cache, "TestClass", "testMethod") == NULL);
rava_methodcache_destroy(cache);
}
TEST(null_params) {
MethodCache_t* cache = rava_methodcache_create();
rava_methodcache_insert(NULL, "Class", "method", NULL);
rava_methodcache_insert(cache, NULL, "method", NULL);
rava_methodcache_insert(cache, "Class", NULL, NULL);
assert(rava_methodcache_lookup(NULL, "Class", "method") == NULL);
assert(rava_methodcache_lookup(cache, NULL, "method") == NULL);
assert(rava_methodcache_lookup(cache, "Class", NULL) == NULL);
rava_methodcache_destroy(cache);
}
TEST(hash_function) {
uint32_t h1 = rava_methodcache_hash("hello");
uint32_t h2 = rava_methodcache_hash("hello");
uint32_t h3 = rava_methodcache_hash("world");
assert(h1 == h2);
assert(h1 != h3);
assert(h1 != 0);
assert(h3 != 0);
}
int main(void) {
printf("=== Method Cache Unit Tests ===\n\n");
RUN_TEST(create_destroy);
RUN_TEST(insert_lookup);
RUN_TEST(lookup_miss);
RUN_TEST(multiple_methods);
RUN_TEST(clear);
RUN_TEST(null_params);
RUN_TEST(hash_function);
printf("\n=== Results: %d tests passed ===\n", tests_passed);
return 0;
}

View File

@ -0,0 +1,149 @@
#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("=== Multi-dimensional Array Tests ===\n\n");
run_test_int("2d array outer length",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[4][5];\n"
" return a.length;\n"
" }\n"
"}\n", 4);
run_test_int("2d array inner length",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[4][5];\n"
" return a[0].length;\n"
" }\n"
"}\n", 5);
run_test_int("2d array basic store and load",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[2][3];\n"
" a[0][1] = 15;\n"
" return a[0][1];\n"
" }\n"
"}\n", 15);
run_test_int("2d array multiple cells",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[2][3];\n"
" a[0][0] = 1;\n"
" a[0][1] = 2;\n"
" a[1][0] = 3;\n"
" a[1][1] = 4;\n"
" return a[0][0] + a[0][1] + a[1][0] + a[1][1];\n"
" }\n"
"}\n", 10);
run_test_int("2d array row iteration",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[3][2];\n"
" a[0][0] = 1; a[0][1] = 2;\n"
" a[1][0] = 3; a[1][1] = 4;\n"
" a[2][0] = 5; a[2][1] = 6;\n"
" int sum = 0;\n"
" for (int i = 0; i < a.length; i++) {\n"
" sum = sum + a[i][0] + a[i][1];\n"
" }\n"
" return sum;\n"
" }\n"
"}\n", 21);
run_test_int("2d array nested loop",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[2][3];\n"
" int v = 1;\n"
" for (int i = 0; i < 2; i++) {\n"
" for (int j = 0; j < 3; j++) {\n"
" a[i][j] = v;\n"
" v = v + 1;\n"
" }\n"
" }\n"
" return a[0][0] + a[0][2] + a[1][1];\n"
" }\n"
"}\n", 9);
run_test_int("2d array different inner lengths",
"public class Test {\n"
" public static int main() {\n"
" int[][] a = new int[3][4];\n"
" int[][] b = new int[2][6];\n"
" return a[0].length + b[0].length;\n"
" }\n"
"}\n", 10);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

Binary file not shown.

146
tests/test_nanbox.c Normal file
View File

@ -0,0 +1,146 @@
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "../runtime/nanbox.h"
static int tests_passed = 0;
static int tests_failed = 0;
#define TEST(name) static void test_##name(void)
#define RUN_TEST(name) do { \
printf("Running %s... ", #name); \
test_##name(); \
printf("PASSED\n"); \
tests_passed++; \
} while(0)
TEST(int_basic) {
RavaNanboxValue_t val = rava_nanbox_int(42);
assert(rava_nanbox_is_int(val));
assert(!rava_nanbox_is_bool(val));
assert(!rava_nanbox_is_null(val));
assert(rava_nanbox_as_int(val) == 42);
}
TEST(int_negative) {
RavaNanboxValue_t val = rava_nanbox_int(-100);
assert(rava_nanbox_is_int(val));
assert(rava_nanbox_as_int(val) == -100);
}
TEST(int_zero) {
RavaNanboxValue_t val = rava_nanbox_int(0);
assert(rava_nanbox_is_int(val));
assert(rava_nanbox_as_int(val) == 0);
}
TEST(long_basic) {
RavaNanboxValue_t val = rava_nanbox_long(1000000000000LL);
assert(rava_nanbox_is_long(val));
int64_t result = rava_nanbox_as_long(val);
(void)result;
}
TEST(bool_true) {
RavaNanboxValue_t val = rava_nanbox_bool(true);
assert(rava_nanbox_is_bool(val));
assert(rava_nanbox_as_bool(val) == true);
}
TEST(bool_false) {
RavaNanboxValue_t val = rava_nanbox_bool(false);
assert(rava_nanbox_is_bool(val));
assert(rava_nanbox_as_bool(val) == false);
}
TEST(null) {
RavaNanboxValue_t val = rava_nanbox_null();
assert(rava_nanbox_is_null(val));
assert(!rava_nanbox_is_int(val));
assert(!rava_nanbox_is_bool(val));
}
TEST(double_basic) {
RavaNanboxValue_t val = rava_nanbox_double(3.14159);
assert(rava_nanbox_is_double(val));
double d = rava_nanbox_as_double(val);
assert(fabs(d - 3.14159) < 0.0001);
}
TEST(double_negative) {
RavaNanboxValue_t val = rava_nanbox_double(-123.456);
assert(rava_nanbox_is_double(val));
double d = rava_nanbox_as_double(val);
assert(fabs(d - (-123.456)) < 0.0001);
}
TEST(conversion_int_to_long) {
RavaNanboxValue_t val = rava_nanbox_int(42);
assert(rava_nanbox_to_long(val) == 42);
}
TEST(conversion_int_to_double) {
RavaNanboxValue_t val = rava_nanbox_int(10);
assert(fabs(rava_nanbox_to_double(val) - 10.0) < 0.0001);
}
TEST(conversion_bool_to_int) {
RavaNanboxValue_t t = rava_nanbox_bool(true);
RavaNanboxValue_t f = rava_nanbox_bool(false);
assert(rava_nanbox_to_int(t) == 1);
assert(rava_nanbox_to_int(f) == 0);
}
TEST(to_bool) {
assert(rava_nanbox_to_bool(rava_nanbox_null()) == false);
assert(rava_nanbox_to_bool(rava_nanbox_bool(true)) == true);
assert(rava_nanbox_to_bool(rava_nanbox_bool(false)) == false);
assert(rava_nanbox_to_bool(rava_nanbox_int(0)) == false);
assert(rava_nanbox_to_bool(rava_nanbox_int(1)) == true);
assert(rava_nanbox_to_bool(rava_nanbox_int(-1)) == true);
}
TEST(object_pointer) {
int dummy = 42;
RavaNanboxValue_t val = rava_nanbox_object(&dummy);
assert(rava_nanbox_is_object(val));
assert(rava_nanbox_as_object(val) == &dummy);
}
TEST(string_pointer) {
const char* str = "hello";
RavaNanboxValue_t val = rava_nanbox_string(str);
assert(rava_nanbox_is_string(val));
assert(rava_nanbox_as_string(val) == str);
}
TEST(array_pointer) {
int arr[10];
RavaNanboxValue_t val = rava_nanbox_array(arr);
assert(rava_nanbox_is_array(val));
assert(rava_nanbox_as_array(val) == arr);
}
int main(void) {
printf("=== NaN Boxing Unit Tests ===\n\n");
RUN_TEST(int_basic);
RUN_TEST(int_negative);
RUN_TEST(int_zero);
RUN_TEST(long_basic);
RUN_TEST(bool_true);
RUN_TEST(bool_false);
RUN_TEST(null);
RUN_TEST(double_basic);
RUN_TEST(double_negative);
RUN_TEST(conversion_int_to_long);
RUN_TEST(conversion_int_to_double);
RUN_TEST(conversion_bool_to_int);
RUN_TEST(to_bool);
RUN_TEST(object_pointer);
RUN_TEST(string_pointer);
RUN_TEST(array_pointer);
printf("\n=== Results: %d passed, %d failed ===\n", tests_passed, tests_failed);
return tests_failed > 0 ? 1 : 0;
}

234
tests/test_negative.c Normal file
View File

@ -0,0 +1,234 @@
#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>
typedef enum {
EXPECT_PARSE_ERROR,
EXPECT_SEMANTIC_ERROR,
EXPECT_RUNTIME_ERROR,
EXPECT_MISSING_CLASS,
EXPECT_MISSING_METHOD
} ExpectedError_e;
static bool test_error(const char *name, const char *source, ExpectedError_e expected,
const char *exec_class, const char *exec_method) {
printf("Test: %-40s ... ", name);
fflush(stdout);
if (!source || strlen(source) == 0) {
printf("PASS (skipped empty input)\n");
return true;
}
RavaLexer_t *lexer = rava_lexer_create(source);
if (!lexer) {
bool success = (expected == EXPECT_PARSE_ERROR);
printf("%s\n", success ? "PASS" : "FAIL");
return success;
}
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
bool success = (expected == EXPECT_PARSE_ERROR);
printf("%s\n", success ? "PASS" : "FAIL");
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return success;
}
if (expected == EXPECT_PARSE_ERROR) {
printf("FAIL (expected parse error)\n");
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return false;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
bool success = (expected == EXPECT_SEMANTIC_ERROR);
printf("%s\n", success ? "PASS" : "FAIL");
rava_semantic_analyzer_destroy(analyzer);
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return success;
}
if (expected == EXPECT_SEMANTIC_ERROR) {
printf("FAIL (expected semantic error)\n");
rava_semantic_analyzer_destroy(analyzer);
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return false;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
bool success = (expected == EXPECT_RUNTIME_ERROR);
printf("%s\n", success ? "PASS" : "FAIL");
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 success;
}
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, exec_class, exec_method)) {
bool success = (expected == EXPECT_RUNTIME_ERROR ||
expected == EXPECT_MISSING_CLASS ||
expected == EXPECT_MISSING_METHOD);
printf("%s\n", success ? "PASS" : "FAIL");
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 success;
}
printf("FAIL (expected error)\n");
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 false;
}
int main(void) {
printf("=== NEGATIVE TEST CASES ===\n\n");
int passed = 0;
int total = 0;
total++;
if (test_error("Missing class body",
"public class Test",
EXPECT_PARSE_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Missing method body",
"public class Test {\n"
" public static int main()\n"
"}\n",
EXPECT_PARSE_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Unclosed brace",
"public class Test {\n"
" public static int main() {\n"
" return 0;\n"
"}\n",
EXPECT_PARSE_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Missing semicolon",
"public class Test {\n"
" public static int main() {\n"
" int x = 5\n"
" return x;\n"
" }\n"
"}\n",
EXPECT_PARSE_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Undefined variable",
"public class Test {\n"
" public static int main() {\n"
" return undefinedVar;\n"
" }\n"
"}\n",
EXPECT_SEMANTIC_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Undefined method call",
"public class Test {\n"
" public static int main() {\n"
" return undefinedMethod();\n"
" }\n"
"}\n",
EXPECT_SEMANTIC_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Missing class at runtime",
"public class Test {\n"
" public static int main() {\n"
" return 0;\n"
" }\n"
"}\n",
EXPECT_MISSING_CLASS, "NonExistent", "main")) {
passed++;
}
total++;
if (test_error("Missing method at runtime",
"public class Test {\n"
" public static int main() {\n"
" return 0;\n"
" }\n"
"}\n",
EXPECT_MISSING_METHOD, "Test", "nonExistent")) {
passed++;
}
total++;
if (test_error("Duplicate variable",
"public class Test {\n"
" public static int main() {\n"
" int x = 5;\n"
" int x = 10;\n"
" return x;\n"
" }\n"
"}\n",
EXPECT_SEMANTIC_ERROR, "Test", "main")) {
passed++;
}
total++;
if (test_error("Malformed for loop",
"public class Test {\n"
" public static int main() {\n"
" for (int i = 0; i < 10) {\n"
" }\n"
" return 0;\n"
" }\n"
"}\n",
EXPECT_PARSE_ERROR, "Test", "main")) {
passed++;
}
printf("\n=== Results: %d/%d tests passed ===\n", passed, total);
return (passed == total) ? 0 : 1;
}

BIN
tests/test_negative.o Normal file

Binary file not shown.

77
tests/test_objects.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/13_SimpleObject.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "SimpleObject", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

BIN
tests/test_objects.o Normal file

Binary file not shown.

17
tests/test_opcode_count.c Normal file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include "../ir/ir.h"
int main(void) {
printf("RAVA_OP_NOP = %d\n", RAVA_OP_NOP);
printf("RAVA_OP_LOAD_CONST = %d\n", RAVA_OP_LOAD_CONST);
printf("RAVA_OP_CALL = %d\n", RAVA_OP_CALL);
printf("RAVA_OP_CALL_STATIC = %d\n", RAVA_OP_CALL_STATIC);
printf("RAVA_OP_CALL_RECURSIVE = %d\n", RAVA_OP_CALL_RECURSIVE);
printf("RAVA_OP_CALL_VIRTUAL = %d\n", RAVA_OP_CALL_VIRTUAL);
printf("RAVA_OP_CALL_SUPER = %d\n", RAVA_OP_CALL_SUPER);
printf("RAVA_OP_CALL_NATIVE = %d\n", RAVA_OP_CALL_NATIVE);
printf("RAVA_OP_RETURN = %d\n", RAVA_OP_RETURN);
printf("RAVA_OP_MATH_RANDOM = %d\n", RAVA_OP_MATH_RANDOM);
printf("Total opcodes: %d\n", RAVA_OP_MATH_RANDOM + 1);
return 0;
}

50
tests/test_parser.c Normal file
View File

@ -0,0 +1,50 @@
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include <stdio.h>
#include <stdlib.h>
extern void rava_ast_print(RavaASTNode_t *node, int depth);
int main() {
const char *source =
"public class Calculator {\n"
" public static int add(int a, int b) {\n"
" int result = a + b;\n"
" return result;\n"
" }\n"
"\n"
" public static void main(String[] args) {\n"
" int x = 10;\n"
" int y = 20;\n"
" int sum = add(x, y);\n"
" if (sum > 0) {\n"
" System.out.println(\"Positive result\");\n"
" }\n"
" }\n"
"}\n";
printf("Source code:\n%s\n", source);
printf("\nAbstract Syntax Tree:\n");
printf("================================================================================\n\n");
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message ? parser->error_message : "Unknown error");
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return 1;
}
rava_ast_print(ast, 0);
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
printf("\nParser test completed successfully!\n");
return 0;
}

BIN
tests/test_parser.o Normal file

Binary file not shown.

91
tests/test_pascal_only.c Normal file
View File

@ -0,0 +1,91 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/08_PascalTriangle.java");
if (!source) return 1;
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
free(source);
return 1;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
free(source);
return 1;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
free(source);
return 1;
}
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "PascalTriangle", "main")) {
printf("Runtime error\n");
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nCleaning up VM...\n");
fflush(stdout);
rava_vm_destroy(vm);
printf("Cleaning up program...\n");
fflush(stdout);
rava_program_destroy(program);
printf("Cleaning up IR generator...\n");
fflush(stdout);
rava_ir_generator_destroy(ir_gen);
printf("Cleaning up analyzer...\n");
fflush(stdout);
rava_semantic_analyzer_destroy(analyzer);
printf("Cleaning up AST...\n");
fflush(stdout);
rava_ast_node_destroy(ast);
printf("Cleaning up parser...\n");
fflush(stdout);
rava_parser_destroy(parser);
printf("Cleaning up lexer...\n");
fflush(stdout);
rava_lexer_destroy(lexer);
printf("Freeing source...\n");
fflush(stdout);
free(source);
printf("Done!\n");
return 0;
}

72
tests/test_println.c Normal file
View File

@ -0,0 +1,72 @@
#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>
int main() {
const char *source =
"public class Test {\n"
" public static int main() {\n"
" System.out.println(42);\n"
" System.out.println(100);\n"
" int x = 10;\n"
" int y = 20;\n"
" System.out.println(x + y);\n"
" return 0;\n"
" }\n"
"}\n";
printf("Source:\n%s\n", source);
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
return 1;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
return 1;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
return 1;
}
printf("\nGenerated IR:\n");
rava_ir_print(program);
RavaVM_t *vm = rava_vm_create(program);
printf("\nExecuting Test.main()...\n");
printf("Output:\n");
if (!rava_vm_execute(vm, "Test", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
return 1;
}
printf("\n✅ Execution completed successfully!\n");
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 0;
}

172
tests/test_runtime.c Normal file
View File

@ -0,0 +1,172 @@
#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>
static bool run_test(const char *name, const char *source, const char *class_name,
const char *method_name, int expected_result) {
printf("\n========================================\n");
printf("Test: %s\n", name);
printf("========================================\n");
printf("Source:\n%s\n", source);
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("❌ Parse error: %s\n", parser->error_message);
return false;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("❌ Semantic error: %s\n", analyzer->error_message);
return false;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("❌ IR generation failed\n");
return false;
}
printf("\nGenerated IR:\n");
rava_ir_print(program);
RavaVM_t *vm = rava_vm_create(program);
printf("\nExecuting %s.%s()...\n", class_name, method_name);
if (!rava_vm_execute(vm, class_name, method_name)) {
printf("❌ Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
return false;
}
RavaValue_t result = rava_vm_get_result(vm);
int32_t result_int = rava_value_as_int(result);
printf("Result: %d\n", result_int);
bool success = (result_int == expected_result);
if (success) {
printf("✅ PASS (expected %d, got %d)\n", expected_result, result_int);
} else {
printf("❌ FAIL (expected %d, got %d)\n", expected_result, 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);
return success;
}
int main() {
printf("================================================================================\n");
printf("RAVA JAVA INTERPRETER - END-TO-END RUNTIME TESTS\n");
printf("================================================================================\n");
int passed = 0;
int total = 0;
total++;
if (run_test("Simple Addition",
"public class Test {\n"
" public static int add() {\n"
" int a = 10;\n"
" int b = 20;\n"
" int result = a + b;\n"
" return result;\n"
" }\n"
"}\n",
"Test", "add", 30)) {
passed++;
}
total++;
if (run_test("Multiple Operations",
"public class Test {\n"
" public static int compute() {\n"
" int a = 5;\n"
" int b = 3;\n"
" int sum = a + b;\n"
" int product = a * b;\n"
" int result = sum + product;\n"
" return result;\n"
" }\n"
"}\n",
"Test", "compute", 23)) {
passed++;
}
total++;
if (run_test("Conditional (True Branch)",
"public class Test {\n"
" public static int conditional() {\n"
" int x = 10;\n"
" int result = 0;\n"
" if (x > 5) {\n"
" result = 100;\n"
" }\n"
" return result;\n"
" }\n"
"}\n",
"Test", "conditional", 100)) {
passed++;
}
total++;
if (run_test("Conditional (False Branch)",
"public class Test {\n"
" public static int conditional() {\n"
" int x = 3;\n"
" int result = 0;\n"
" if (x > 5) {\n"
" result = 100;\n"
" }\n"
" return result;\n"
" }\n"
"}\n",
"Test", "conditional", 0)) {
passed++;
}
total++;
if (run_test("Factorial (Recursive)",
"public class Test {\n"
" public static int factorial(int n) {\n"
" if (n <= 1) {\n"
" return 1;\n"
" }\n"
" return n * factorial(n - 1);\n"
" }\n"
"}\n",
"Test", "factorial", 1)) {
passed++;
}
printf("\n================================================================================\n");
printf("TEST SUMMARY\n");
printf("================================================================================\n");
printf("Passed: %d/%d\n", passed, total);
printf("Failed: %d/%d\n", total - passed, total);
if (passed == total) {
printf("\n🎉 ALL TESTS PASSED! The Rava interpreter is executing Java code!\n");
} else {
printf("\n⚠️ Some tests failed.\n");
}
return (passed == total) ? 0 : 1;
}

BIN
tests/test_runtime.o Normal file

Binary file not shown.

74
tests/test_semantic.c Normal file
View File

@ -0,0 +1,74 @@
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include "../semantic/semantic.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *source =
"public class Test {\n"
" public static int calculate(int x, int y) {\n"
" int sum = x + y;\n"
" int product = x * y;\n"
" boolean isPositive = sum > 0;\n"
" if (isPositive) {\n"
" return sum;\n"
" }\n"
" return product;\n"
" }\n"
"\n"
" public static void main(int argc) {\n"
" int result = calculate(10, 20);\n"
" int doubled = result * 2;\n"
" }\n"
"}\n";
printf("Source code:\n%s\n", source);
printf("\nSemantic Analysis:\n");
printf("================================================================================\n\n");
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message ? parser->error_message : "Unknown error");
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
return 1;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
bool success = rava_semantic_analyze(analyzer, ast);
if (success) {
printf("✓ Semantic analysis passed successfully!\n\n");
printf("Symbol table contains:\n");
printf("- Class: Test\n");
printf(" - Method: calculate (returns int)\n");
printf(" - Parameter: x (int)\n");
printf(" - Parameter: y (int)\n");
printf(" - Variable: sum (int)\n");
printf(" - Variable: product (int)\n");
printf(" - Variable: isPositive (boolean)\n");
printf(" - Method: main (returns void)\n");
printf(" - Parameter: argc (int)\n");
printf(" - Variable: result (int)\n");
printf(" - Variable: doubled (int)\n");
} else {
printf("✗ Semantic analysis failed!\n");
if (analyzer->error_message) {
printf("Error: %s\n", analyzer->error_message);
}
printf("Total errors: %d\n", analyzer->error_count);
}
rava_semantic_analyzer_destroy(analyzer);
rava_ast_node_destroy(ast);
rava_parser_destroy(parser);
rava_lexer_destroy(lexer);
printf("\nSemantic test completed!\n");
return success ? 0 : 1;
}

BIN
tests/test_semantic.o Normal file

Binary file not shown.

165
tests/test_shortcircuit.c Normal file
View File

@ -0,0 +1,165 @@
#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;
}

BIN
tests/test_shortcircuit.o Normal file

Binary file not shown.

135
tests/test_static.c Normal file
View File

@ -0,0 +1,135 @@
#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("=== Static Field Tests ===\n\n");
run_test_int("static field basic read/write",
"class Counter {\n"
" static int count;\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Counter.count = 42;\n"
" return Counter.count;\n"
" }\n"
"}\n", 42);
run_test_int("static field increment",
"class Counter {\n"
" static int count;\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Counter.count = 10;\n"
" Counter.count = Counter.count + 5;\n"
" return Counter.count;\n"
" }\n"
"}\n", 15);
run_test_int("static field in same class",
"public class Test {\n"
" static int value;\n"
" public static int main() {\n"
" Test.value = 100;\n"
" return Test.value;\n"
" }\n"
"}\n", 100);
run_test_int("multiple static fields",
"class Data {\n"
" static int a;\n"
" static int b;\n"
" static int c;\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Data.a = 10;\n"
" Data.b = 20;\n"
" Data.c = 30;\n"
" return Data.a + Data.b + Data.c;\n"
" }\n"
"}\n", 60);
run_test_int("static field across classes",
"class ClassA {\n"
" static int val;\n"
"}\n"
"class ClassB {\n"
" static int val;\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" ClassA.val = 100;\n"
" ClassB.val = 200;\n"
" return ClassA.val + ClassB.val;\n"
" }\n"
"}\n", 300);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_static.o Normal file

Binary file not shown.

View File

@ -0,0 +1,40 @@
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include <stdio.h>
#include <stdlib.h>
static char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/11_TowerOfHanoiStatic.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parsed successfully!\n");
free(source);
return 0;
}

134
tests/test_static_init.c Normal file
View File

@ -0,0 +1,134 @@
#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("=== Static Field Initializer Tests ===\n\n");
run_test_int("static field with literal initializer",
"public class Test {\n"
" static int v = 42;\n"
" public static int main() {\n"
" return Test.v;\n"
" }\n"
"}\n", 42);
run_test_int("static field with expression initializer",
"public class Test {\n"
" static int v = 10 + 32;\n"
" public static int main() {\n"
" return Test.v;\n"
" }\n"
"}\n", 42);
run_test_int("multiple static fields with initializers",
"public class Test {\n"
" static int a = 10;\n"
" static int b = 20;\n"
" static int c = 12;\n"
" public static int main() {\n"
" return Test.a + Test.b + Test.c;\n"
" }\n"
"}\n", 42);
run_test_int("static field initializer can be overwritten",
"public class Test {\n"
" static int v = 10;\n"
" public static int main() {\n"
" Test.v = 42;\n"
" return Test.v;\n"
" }\n"
"}\n", 42);
run_test_int("static field used in expression",
"public class Test {\n"
" static int base = 40;\n"
" public static int main() {\n"
" return Test.base + 2;\n"
" }\n"
"}\n", 42);
run_test_int("static field in different class",
"class Data {\n"
" static int value = 42;\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" return Data.value;\n"
" }\n"
"}\n", 42);
run_test_int("static field with negative initializer",
"public class Test {\n"
" static int v = 100 - 58;\n"
" public static int main() {\n"
" return Test.v;\n"
" }\n"
"}\n", 42);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_static_init.o Normal file

Binary file not shown.

253
tests/test_string_methods.c Normal file
View File

@ -0,0 +1,253 @@
#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("=== String Methods Tests ===\n\n");
run_test_int("String.length",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello\";\n"
" return s.length();\n"
" }\n"
"}\n", 5);
run_test_int("String.charAt",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello\";\n"
" return s.charAt(1);\n"
" }\n"
"}\n", 'e');
run_test_int("String.substring",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" String sub = s.substring(0, 5);\n"
" return sub.length();\n"
" }\n"
"}\n", 5);
run_test_int("String.equals true",
"public class Test {\n"
" public static int main() {\n"
" String a = \"test\";\n"
" String b = \"test\";\n"
" if (a.equals(b)) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("String.equals false",
"public class Test {\n"
" public static int main() {\n"
" String a = \"test\";\n"
" String b = \"other\";\n"
" if (a.equals(b)) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test_int("String.compareTo equal",
"public class Test {\n"
" public static int main() {\n"
" String a = \"abc\";\n"
" String b = \"abc\";\n"
" return a.compareTo(b);\n"
" }\n"
"}\n", 0);
run_test_int("String.compareTo less",
"public class Test {\n"
" public static int main() {\n"
" String a = \"abc\";\n"
" String b = \"abd\";\n"
" if (a.compareTo(b) < 0) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("String.compareTo greater",
"public class Test {\n"
" public static int main() {\n"
" String a = \"abd\";\n"
" String b = \"abc\";\n"
" if (a.compareTo(b) > 0) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("String.indexOf found",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" return s.indexOf(\"World\");\n"
" }\n"
"}\n", 6);
run_test_int("String.indexOf not found",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" return s.indexOf(\"xyz\");\n"
" }\n"
"}\n", -1);
run_test_int("String.contains true",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" if (s.contains(\"World\")) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("String.contains false",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" if (s.contains(\"xyz\")) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test_int("String.startsWith true",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" if (s.startsWith(\"Hello\")) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("String.startsWith false",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" if (s.startsWith(\"World\")) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test_int("String.endsWith true",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" if (s.endsWith(\"World\")) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 1);
run_test_int("String.endsWith false",
"public class Test {\n"
" public static int main() {\n"
" String s = \"Hello World\";\n"
" if (s.endsWith(\"Hello\")) { return 1; }\n"
" return 0;\n"
" }\n"
"}\n", 0);
run_test_int("String.toLowerCase length",
"public class Test {\n"
" public static int main() {\n"
" String s = \"HELLO\";\n"
" String lower = s.toLowerCase();\n"
" return lower.length();\n"
" }\n"
"}\n", 5);
run_test_int("String.toLowerCase charAt",
"public class Test {\n"
" public static int main() {\n"
" String s = \"HELLO\";\n"
" String lower = s.toLowerCase();\n"
" return lower.charAt(0);\n"
" }\n"
"}\n", 'h');
run_test_int("String.toUpperCase charAt",
"public class Test {\n"
" public static int main() {\n"
" String s = \"hello\";\n"
" String upper = s.toUpperCase();\n"
" return upper.charAt(0);\n"
" }\n"
"}\n", 'H');
run_test_int("String.trim length",
"public class Test {\n"
" public static int main() {\n"
" String s = \" Hello \";\n"
" String trimmed = s.trim();\n"
" return trimmed.length();\n"
" }\n"
"}\n", 5);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_string_methods.o Normal file

Binary file not shown.

77
tests/test_strings.c Normal file
View File

@ -0,0 +1,77 @@
#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 char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file);
content[read_bytes] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/12_StringBasics.java");
if (!source) {
printf("Failed to read file\n");
return 1;
}
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
printf("Parse: OK\n");
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
printf("Semantic: OK\n");
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
printf("IR Gen: OK\n");
printf("\nOutput:\n");
RavaVM_t *vm = rava_vm_create(program);
if (!rava_vm_execute(vm, "StringBasics", "main")) {
printf("Runtime error: %s\n", vm->error_message);
rava_vm_destroy(vm);
free(source);
return 1;
}
printf("\nExecution: OK\n");
rava_vm_destroy(vm);
free(source);
return 0;
}

BIN
tests/test_strings.o Normal file

Binary file not shown.

132
tests/test_super.c Normal file
View File

@ -0,0 +1,132 @@
#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("=== Super Keyword Tests ===\n\n");
run_test_int("super.method() basic",
"class Parent {\n"
" int getValue() {\n"
" return 10;\n"
" }\n"
"}\n"
"class Child extends Parent {\n"
" int getValue() {\n"
" return super.getValue() + 5;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Child c = new Child();\n"
" return c.getValue();\n"
" }\n"
"}\n", 15);
run_test_int("super.method() with args",
"class Parent {\n"
" int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"}\n"
"class Child extends Parent {\n"
" int add(int a, int b) {\n"
" return super.add(a, b) * 2;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Child c = new Child();\n"
" return c.add(3, 4);\n"
" }\n"
"}\n", 14);
run_test_int("super.method() chain",
"class GrandParent {\n"
" int getValue() {\n"
" return 100;\n"
" }\n"
"}\n"
"class Parent extends GrandParent {\n"
" int getValue() {\n"
" return super.getValue() + 10;\n"
" }\n"
"}\n"
"class Child extends Parent {\n"
" int getValue() {\n"
" return super.getValue() + 1;\n"
" }\n"
"}\n"
"public class Test {\n"
" public static int main() {\n"
" Child c = new Child();\n"
" return c.getValue();\n"
" }\n"
"}\n", 111);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

166
tests/test_switch.c Normal file
View File

@ -0,0 +1,166 @@
#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(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\n", name);
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("=== Switch/Case Tests ===\n\n");
run_test("Simple switch",
"public class Test {\n"
" public static int main() {\n"
" int x = 2;\n"
" int result = 0;\n"
" switch (x) {\n"
" case 1:\n"
" result = 10;\n"
" break;\n"
" case 2:\n"
" result = 20;\n"
" break;\n"
" case 3:\n"
" result = 30;\n"
" break;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 20);
run_test("Switch with default",
"public class Test {\n"
" public static int main() {\n"
" int x = 99;\n"
" int result = 0;\n"
" switch (x) {\n"
" case 1:\n"
" result = 10;\n"
" break;\n"
" case 2:\n"
" result = 20;\n"
" break;\n"
" default:\n"
" result = 100;\n"
" break;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 100);
run_test("Switch fallthrough",
"public class Test {\n"
" public static int main() {\n"
" int x = 1;\n"
" int result = 0;\n"
" switch (x) {\n"
" case 1:\n"
" result = result + 10;\n"
" case 2:\n"
" result = result + 20;\n"
" break;\n"
" case 3:\n"
" result = result + 30;\n"
" break;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 30);
run_test("Switch first case",
"public class Test {\n"
" public static int main() {\n"
" int x = 1;\n"
" int result = 0;\n"
" switch (x) {\n"
" case 1:\n"
" result = 111;\n"
" break;\n"
" case 2:\n"
" result = 222;\n"
" break;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 111);
run_test("Switch no match no default",
"public class Test {\n"
" public static int main() {\n"
" int x = 99;\n"
" int result = 42;\n"
" switch (x) {\n"
" case 1:\n"
" result = 10;\n"
" break;\n"
" case 2:\n"
" result = 20;\n"
" break;\n"
" }\n"
" return result;\n"
" }\n"
"}\n", 42);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_switch.o Normal file

Binary file not shown.

140
tests/test_ternary.c Normal file
View File

@ -0,0 +1,140 @@
#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("=== Ternary Operator Tests ===\n\n");
run_test_int("ternary true condition",
"public class Test {\n"
" public static int main() {\n"
" return 1 == 1 ? 42 : 0;\n"
" }\n"
"}\n", 42);
run_test_int("ternary false condition",
"public class Test {\n"
" public static int main() {\n"
" return 1 == 2 ? 42 : 99;\n"
" }\n"
"}\n", 99);
run_test_int("ternary with variables",
"public class Test {\n"
" public static int main() {\n"
" int x = 10;\n"
" int y = 20;\n"
" return x < y ? x : y;\n"
" }\n"
"}\n", 10);
run_test_int("ternary min value",
"public class Test {\n"
" public static int main() {\n"
" int a = 5;\n"
" int b = 3;\n"
" return a < b ? a : b;\n"
" }\n"
"}\n", 3);
run_test_int("ternary max value",
"public class Test {\n"
" public static int main() {\n"
" int a = 5;\n"
" int b = 3;\n"
" return a > b ? a : b;\n"
" }\n"
"}\n", 5);
run_test_int("nested ternary",
"public class Test {\n"
" public static int main() {\n"
" int x = 2;\n"
" return x == 1 ? 10 : (x == 2 ? 20 : 30);\n"
" }\n"
"}\n", 20);
run_test_int("ternary in variable assignment",
"public class Test {\n"
" public static int main() {\n"
" int x = 5;\n"
" int result = x > 3 ? 100 : 200;\n"
" return result;\n"
" }\n"
"}\n", 100);
run_test_int("ternary with arithmetic",
"public class Test {\n"
" public static int main() {\n"
" int a = 4;\n"
" int b = 6;\n"
" return a + b > 8 ? a * b : a + b;\n"
" }\n"
"}\n", 24);
printf("\n=== Results: %d/%d tests passed ===\n", pass_count, test_count);
return (pass_count == test_count) ? 0 : 1;
}

BIN
tests/test_ternary.o Normal file

Binary file not shown.

56
tests/test_tower_ir.c Normal file
View File

@ -0,0 +1,56 @@
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include "../semantic/semantic.h"
#include "../ir/ir.h"
#include "../ir/ir_gen.h"
#include <stdio.h>
#include <stdlib.h>
static char* read_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *content = malloc(size + 1);
size_t read_bytes = fread(content, 1, size, file); (void)read_bytes;
content[size] = '\0';
fclose(file);
return content;
}
int main() {
char *source = read_file("examples/09_TowerOfHanoi.java");
if (!source) return 1;
RavaLexer_t *lexer = rava_lexer_create(source);
RavaParser_t *parser = rava_parser_create(lexer);
RavaASTNode_t *ast = rava_parser_parse(parser);
if (parser->had_error) {
printf("Parse error: %s\n", parser->error_message);
free(source);
return 1;
}
RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create();
if (!rava_semantic_analyze(analyzer, ast)) {
printf("Semantic error: %s\n", analyzer->error_message);
free(source);
return 1;
}
RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer);
RavaProgram_t *program = rava_ir_generate(ir_gen, ast);
if (!program) {
printf("IR generation failed\n");
free(source);
return 1;
}
rava_program_print(program);
free(source);
return 0;
}