Compare commits

...

2 Commits

Author SHA1 Message Date
7d0b195772 Clean up.
All checks were successful
CI / Optimization Infrastructure Tests (push) Successful in 18s
CI / Unit Tests (push) Successful in 20s
CI / Integration Tests (push) Successful in 24s
CI / Performance Benchmark (push) Successful in 1m25s
2025-12-09 19:41:09 +01:00
81792197ff Clean up. 2025-12-09 19:41:05 +01:00
17 changed files with 462 additions and 453 deletions

View File

@ -35,7 +35,7 @@ jobs:
gcc -Wall -Wextra -std=gnu99 -O3 -march=native -I. -fprofile-use -fprofile-correction \
-o test_benchmark_pgo \
lexer/lexer_tokenizer.c lexer/lexer_keywords.c lexer/lexer_literals.c \
parser/parser.c parser/parser_expressions.c parser/parser_statements.c parser/parser_declarations.c parser/parser_printer.c \
parser/parser.c parser/parser_expressions.c parser/parser_statements.c parser/parser_declarations.c \
types/types.c \
semantic/symbol_table.c semantic/semantic.c \
ir/ir.c ir/ir_gen.c \

4
.gitignore vendored
View File

@ -6,3 +6,7 @@ merge.py
*.o
run_examples
rava
*.gcno
*.gcda
coverage_report
*.info

122
Makefile
View File

@ -5,7 +5,7 @@ LDFLAGS = -ldl -lm
LEXER_SOURCES = lexer/lexer_tokenizer.c lexer/lexer_keywords.c lexer/lexer_literals.c
LEXER_OBJECTS = $(LEXER_SOURCES:.c=.o)
PARSER_SOURCES = parser/parser.c parser/parser_expressions.c parser/parser_statements.c parser/parser_declarations.c parser/parser_printer.c
PARSER_SOURCES = parser/parser.c parser/parser_expressions.c parser/parser_statements.c parser/parser_declarations.c
PARSER_OBJECTS = $(PARSER_SOURCES:.c=.o)
TYPES_SOURCES = types/types.c
@ -391,7 +391,125 @@ clean:
test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio test_dowhile test_switch test_math test_string_methods test_static test_interfaces test_exceptions test_ternary test_bitwise test_enhanced_for test_array_init test_instanceof test_shortcircuit test_multidim_arrays test_static_init test_negative test_enums test_collections test_super test_inheritance test_break test_elseif test_forloop test_println test_loader test_object_methods test_autobox test_sockets test_method_ref test_gc test_benchmark \
test_nanbox test_fastframe test_labeltable test_methodcache test_benchmark_pgo test_unittest_demo rava rava.o *.gcda */*.gcda
.PHONY: all clean benchmark test_phase0 pgo test_benchmark_pgo_gen pgo_run test_benchmark_pgo test test_repl examples
.PHONY: all clean benchmark test_phase0 pgo test_benchmark_pgo_gen pgo_run test_benchmark_pgo test test_repl examples coverage coverage-clean coverage-report
COVERAGE_CFLAGS = -Wall -Wextra -Werror -std=gnu99 -O0 -g --coverage -I.
COVERAGE_LDFLAGS = -ldl -lm --coverage
coverage-clean:
rm -f *.gcda *.gcno *.gcov
rm -f */*.gcda */*.gcno */*.gcov
rm -f */*/*.gcda */*/*.gcno */*/*.gcov
rm -rf coverage_report
coverage: coverage-clean
@echo "=== Building with coverage instrumentation ==="
$(MAKE) clean
$(MAKE) CC="$(CC)" CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
$(MAKE) CC="$(CC)" CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" test_overloading test_overloading_runtime
@echo ""
@echo "=== Running ALL tests to collect coverage data ==="
-./test_lexer
-./test_parser
-./test_semantic
-./test_ir
-./test_runtime
-./test_strings
-./test_arrays
-./test_objects
-./test_instance_methods
-./test_fileio
-./test_dowhile
-./test_switch
-./test_math
-./test_string_methods
-./test_static
-./test_static_init
-./test_interfaces
-./test_exceptions
-./test_ternary
-./test_bitwise
-./test_enhanced_for
-./test_array_init
-./test_instanceof
-./test_shortcircuit
-./test_multidim_arrays
-./test_negative
-./test_enums
-./test_collections
-./test_super
-./test_inheritance
-./test_break
-./test_elseif
-./test_forloop
-./test_println
-./test_loader
-./test_object_methods
-./test_autobox
-./test_sockets
-./test_method_ref
-./test_gc
-./test_nanbox
-./test_fastframe
-./test_labeltable
-./test_methodcache
-./test_benchmark
-./test_overloading
-./test_overloading_runtime
@echo ""
@echo "=== Running ALL example programs ==="
-./rava examples/01_Fibonacci.java Fibonacci main
-./rava examples/02_PrimeNumbers.java PrimeNumbers main
-./rava examples/03_FactorialVariations.java FactorialVariations main
-./rava examples/04_GCD_LCM.java GCD_LCM main
-./rava examples/05_PowerFunction.java PowerFunction main
-./rava examples/06_ArrayOperations.java ArrayOperations main
-./rava examples/06_BubbleSort.java BubbleSort main
-./rava examples/07_CollatzConjecture.java CollatzConjecture main
-./rava examples/08_PascalTriangle.java PascalTriangle main
-./rava examples/09_TowerOfHanoi.java TowerOfHanoi main
-./rava examples/10_AckermannFunction.java AckermannFunction main
-./rava examples/11_ArrayOperations.java ArrayOperations main
-./rava examples/11_SimpleArray.java SimpleArray main
-./rava examples/11_TowerOfHanoiStatic.java TowerOfHanoiStatic main
-./rava examples/12_StringBasics.java StringBasics main
-./rava examples/13_SimpleObject.java SimpleObject main
-./rava examples/14_InstanceMethods.java InstanceMethods main
-./rava examples/15_FileIO.java FileIO main
-./rava examples/16_ForLoop.java ForLoop main
-./rava examples/17_Inheritance.java Inheritance main
-./rava examples/18_ElseIf.java ElseIf main
-./rava examples/19_BreakContinue.java BreakContinue main
-./rava examples/20_Benchmark.java Benchmark main
-./rava examples/21_DoWhile.java DoWhile main
-./rava examples/HelloWorld.java HelloWorld main
@echo ""
@echo "=== Generating coverage report ==="
$(MAKE) coverage-report
coverage-report:
@echo "=== Coverage Summary ==="
@echo ""
@for dir in lexer parser types semantic ir runtime loader; do \
echo "--- $$dir/ ---"; \
for f in $$dir/*.c; do \
gcov -n "$$f" 2>/dev/null | grep -A1 "^File" | grep -v "^--$$" || true; \
done; \
echo ""; \
done
@echo "=== Detailed .gcov files generated in source directories ==="
@echo "Run 'gcov <file.c>' for detailed line-by-line coverage"
@echo "Run 'make coverage-html' for HTML report (requires lcov)"
coverage-html:
@echo "=== Generating HTML coverage report ==="
@which lcov > /dev/null || (echo "ERROR: lcov not installed. Run: sudo apt-get install lcov" && exit 1)
lcov --capture --directory . --output-file coverage.info --ignore-errors inconsistent,unused
lcov --remove coverage.info '/usr/*' '*/tests/*' --output-file coverage.info --ignore-errors inconsistent,unused
genhtml coverage.info --output-directory coverage_report --ignore-errors inconsistent,unused
@echo ""
@echo "=== HTML report generated in coverage_report/ ==="
@xdg-open coverage_report/index.html 2>/dev/null || open coverage_report/index.html 2>/dev/null || echo "Open coverage_report/index.html in a browser"
test: all
@echo "=== Running All Tests ==="

View File

@ -325,9 +325,23 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
break;
case RAVA_OP_CALL_STATIC: {
RavaMethod_t *method = _rava_vm_find_method_cached(vm,
int arg_count = instr->operand.call.arg_count;
RavaMethod_t *method = (RavaMethod_t*)instr->operand.call.cached_method;
if (!method) {
RavaValue_t *args = arg_count > 0 ? &stack->values[stack->top - arg_count] : NULL;
method = _rava_vm_find_method_overload(vm,
instr->operand.call.class_name,
instr->operand.call.method_name,
args, (size_t)arg_count);
if (!method) {
method = _rava_vm_find_method_cached(vm,
instr->operand.call.class_name,
instr->operand.call.method_name);
}
if (method) {
instr->operand.call.cached_method = method;
}
}
if (!method) {
vm->had_error = true;
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
@ -339,7 +353,7 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
RavaCallFrame_t *new_frame = rava_call_frame_create(method);
for (int i = instr->operand.call.arg_count - 1; i >= 0; i--) {
for (int i = arg_count - 1; i >= 0; i--) {
new_frame->locals[i] = rava_stack_pop(stack);
}
@ -387,7 +401,11 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
class_name = obj_val.data.object_val->class_name;
}
RavaMethod_t *method = _rava_vm_find_method_cached(vm, class_name, instr->operand.call.method_name);
RavaMethod_t *method = _rava_vm_find_method_overload(vm, class_name, instr->operand.call.method_name,
args, (size_t)instr->operand.call.arg_count);
if (!method) {
method = _rava_vm_find_method_cached(vm, class_name, instr->operand.call.method_name);
}
if (!method) {
if (strcmp(instr->operand.call.method_name, "<init>") == 0 && instr->operand.call.arg_count == 0) {
break;
@ -467,7 +485,11 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
RavaValue_t obj_val = rava_stack_pop(stack);
const char *super_class = instr->operand.call.class_name;
RavaMethod_t *method = _rava_vm_find_method_cached(vm, super_class, instr->operand.call.method_name);
RavaMethod_t *method = _rava_vm_find_method_overload(vm, super_class, instr->operand.call.method_name,
args, (size_t)instr->operand.call.arg_count);
if (!method) {
method = _rava_vm_find_method_cached(vm, super_class, instr->operand.call.method_name);
}
if (!method) {
vm->had_error = true;
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
@ -3640,8 +3662,23 @@ uf_label:
uf_call:
uf_call_static: {
RavaMethod_t *target = _rava_vm_find_method_cached(vm,
instr->operand.call.class_name, instr->operand.call.method_name);
RavaNanboxValue_t args[16];
for (int i = instr->operand.call.arg_count - 1; i >= 0; i--) {
args[i] = UF_POP();
}
RavaMethod_t *target = (RavaMethod_t*)instr->operand.call.cached_method;
if (!target) {
target = _rava_vm_find_method_overload_nb(vm,
instr->operand.call.class_name, instr->operand.call.method_name,
args, (size_t)instr->operand.call.arg_count);
if (!target) {
target = _rava_vm_find_method_cached(vm,
instr->operand.call.class_name, instr->operand.call.method_name);
}
if (target) {
instr->operand.call.cached_method = target;
}
}
if (!target) {
vm->had_error = true;
goto uf_done;
@ -3650,10 +3687,6 @@ uf_call_static: {
rava_optimize_superinstructions(target);
target->label_table = rava_labeltable_create(target->instructions);
}
RavaNanboxValue_t args[16];
for (int i = instr->operand.call.arg_count - 1; i >= 0; i--) {
args[i] = UF_POP();
}
frame->pc = pc;
FastFrame_t *new_frame = rava_fastframe_push(target, target->local_count);
if (!new_frame) {
@ -3767,7 +3800,11 @@ uf_call_virtual: {
}
RavaObject_t *obj = rava_nanbox_as_object(obj_val);
const char *class_name = obj->class_name;
RavaMethod_t *target = _rava_vm_find_method_cached(vm, class_name, instr->operand.call.method_name);
RavaMethod_t *target = _rava_vm_find_method_overload_nb(vm, class_name, instr->operand.call.method_name,
args, (size_t)arg_count);
if (!target) {
target = _rava_vm_find_method_cached(vm, class_name, instr->operand.call.method_name);
}
if (!target) {
if (strcmp(mname, "<init>") == 0 && arg_count == 0) {
UF_DISPATCH();
@ -3824,7 +3861,11 @@ uf_call_super: {
}
RavaNanboxValue_t obj_val = UF_POP();
const char *super_class = instr->operand.call.class_name;
RavaMethod_t *target = _rava_vm_find_method_cached(vm, super_class, instr->operand.call.method_name);
RavaMethod_t *target = _rava_vm_find_method_overload_nb(vm, super_class, instr->operand.call.method_name,
args, (size_t)arg_count);
if (!target) {
target = _rava_vm_find_method_cached(vm, super_class, instr->operand.call.method_name);
}
if (!target) {
vm->had_error = true;
goto uf_done;

View File

@ -154,6 +154,7 @@ RavaClass_t* _rava_vm_find_class(RavaVM_t *vm, const char *class_name);
RavaMethod_t* _rava_vm_find_method(RavaVM_t *vm, const char *class_name, const char *method_name);
RavaMethod_t* _rava_vm_find_method_cached(RavaVM_t *vm, const char *class_name, const char *method_name);
RavaMethod_t* _rava_vm_find_method_overload(RavaVM_t *vm, const char *class_name, const char *method_name, RavaValue_t *args, size_t arg_count);
RavaMethod_t* _rava_vm_find_method_overload_nb(RavaVM_t *vm, const char *class_name, const char *method_name, RavaNanboxValue_t *args, size_t arg_count);
RavaStaticFieldTable_t* rava_static_field_table_create(void);
void rava_static_field_table_destroy(RavaStaticFieldTable_t *table);

View File

@ -119,3 +119,15 @@ RavaMethod_t* _rava_vm_find_method_cached(RavaVM_t *vm, const char *class_name,
}
return method;
}
RavaMethod_t* _rava_vm_find_method_overload_nb(RavaVM_t *vm, const char *class_name, const char *method_name, RavaNanboxValue_t *args, size_t arg_count) {
if (arg_count == 0) {
return _rava_vm_find_method_overload(vm, class_name, method_name, NULL, 0);
}
RavaValue_t converted_args[16];
size_t count = arg_count > 16 ? 16 : arg_count;
for (size_t i = 0; i < count; i++) {
converted_args[i] = rava_nanbox_to_value(args[i]);
}
return _rava_vm_find_method_overload(vm, class_name, method_name, converted_args, count);
}

View File

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

View File

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

View File

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

View File

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

171
tests/test_overloading.c Normal file
View File

@ -0,0 +1,171 @@
#include "unittest.h"
#include "../lexer/lexer.h"
#include "../parser/parser.h"
#include "../semantic/semantic.h"
#include "../ir/ir_gen.h"
#include "../runtime/runtime.h"
UnittestTestResult_t* test_overloading_different_param_count(void) {
UNITTEST_BEGIN_TEST("TestMethodOverloading", "test_different_param_count");
const char* source =
"public class Calculator {\n"
" public static int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"\n"
" public static int add(int a, int b, int c) {\n"
" return a + b + c;\n"
" }\n"
"}\n";
RavaLexer_t* lexer = rava_lexer_create(source);
UNITTEST_ASSERT_NOT_NULL(_unittest_result, lexer, "lexer should be created");
RavaParser_t* parser = rava_parser_create(lexer);
UNITTEST_ASSERT_NOT_NULL(_unittest_result, parser, "parser should be created");
RavaASTNode_t* ast = rava_parser_parse(parser);
UNITTEST_ASSERT_NOT_NULL(_unittest_result, ast, "AST should be created");
RavaSemanticAnalyzer_t* semantic = rava_semantic_analyzer_create();
UNITTEST_ASSERT_NOT_NULL(_unittest_result, semantic, "semantic analyzer should be created");
bool success = rava_semantic_analyze(semantic, ast);
UNITTEST_ASSERT_TRUE(_unittest_result, success, "semantic analysis should accept overloaded methods with different param counts");
UNITTEST_END_TEST();
}
UnittestTestResult_t* test_overloading_different_param_types(void) {
UNITTEST_BEGIN_TEST("TestMethodOverloading", "test_different_param_types");
const char* source =
"public class Calculator {\n"
" public static int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"\n"
" public static double add(double a, double b) {\n"
" return a + b;\n"
" }\n"
"}\n";
RavaLexer_t* lexer = rava_lexer_create(source);
RavaParser_t* parser = rava_parser_create(lexer);
RavaASTNode_t* ast = rava_parser_parse(parser);
RavaSemanticAnalyzer_t* semantic = rava_semantic_analyzer_create();
bool success = rava_semantic_analyze(semantic, ast);
UNITTEST_ASSERT_TRUE(_unittest_result, success, "semantic analysis should accept overloaded methods with different param types");
UNITTEST_END_TEST();
}
UnittestTestResult_t* test_overloading_reject_duplicate_signature(void) {
UNITTEST_BEGIN_TEST("TestMethodOverloading", "test_reject_duplicate_signature");
const char* source =
"public class Calculator {\n"
" public static int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"\n"
" public static int add(int x, int y) {\n"
" return x + y;\n"
" }\n"
"}\n";
RavaLexer_t* lexer = rava_lexer_create(source);
RavaParser_t* parser = rava_parser_create(lexer);
RavaASTNode_t* ast = rava_parser_parse(parser);
RavaSemanticAnalyzer_t* semantic = rava_semantic_analyzer_create();
bool success = rava_semantic_analyze(semantic, ast);
UNITTEST_ASSERT_FALSE(_unittest_result, success, "semantic analysis should reject duplicate method signatures");
UNITTEST_END_TEST();
}
UnittestTestResult_t* test_overloading_mixed_param_types(void) {
UNITTEST_BEGIN_TEST("TestMethodOverloading", "test_mixed_param_types");
const char* source =
"public class Calculator {\n"
" public static int add(int a, double b) {\n"
" return a + (int)b;\n"
" }\n"
"\n"
" public static double add(double a, int b) {\n"
" return a + (double)b;\n"
" }\n"
"}\n";
RavaLexer_t* lexer = rava_lexer_create(source);
RavaParser_t* parser = rava_parser_create(lexer);
RavaASTNode_t* ast = rava_parser_parse(parser);
RavaSemanticAnalyzer_t* semantic = rava_semantic_analyzer_create();
bool success = rava_semantic_analyze(semantic, ast);
UNITTEST_ASSERT_TRUE(_unittest_result, success, "semantic analysis should accept overloaded methods with mixed param types");
UNITTEST_END_TEST();
}
UnittestTestResult_t* test_overloading_three_overloads(void) {
UNITTEST_BEGIN_TEST("TestMethodOverloading", "test_three_overloads");
const char* source =
"public class Math {\n"
" public static int max(int a, int b) {\n"
" return a > b ? a : b;\n"
" }\n"
"\n"
" public static double max(double a, double b) {\n"
" return a > b ? a : b;\n"
" }\n"
"\n"
" public static int max(int a, int b, int c) {\n"
" return a > b ? (a > c ? a : c) : (b > c ? b : c);\n"
" }\n"
"}\n";
RavaLexer_t* lexer = rava_lexer_create(source);
RavaParser_t* parser = rava_parser_create(lexer);
RavaASTNode_t* ast = rava_parser_parse(parser);
RavaSemanticAnalyzer_t* semantic = rava_semantic_analyzer_create();
bool success = rava_semantic_analyze(semantic, ast);
UNITTEST_ASSERT_TRUE(_unittest_result, success, "semantic analysis should accept three overloads of max()");
UNITTEST_END_TEST();
}
int main(int argc, char **argv) {
UnittestConfig_t *config = unittest_config_create();
config->verbosity = 2;
config->track_execution_time = true;
if (argc > 1 && strcmp(argv[1], "--json") == 0) {
config->output_format = UNITTEST_FORMAT_JSON;
config->use_colors = false;
}
UnittestTestSuite_t *suite = unittest_test_suite_create("Method Overloading Tests");
UnittestTestCase_t *tc = unittest_test_case_create("TestMethodOverloading");
unittest_test_case_add_result(tc, test_overloading_different_param_count());
unittest_test_case_add_result(tc, test_overloading_different_param_types());
unittest_test_case_add_result(tc, test_overloading_reject_duplicate_signature());
unittest_test_case_add_result(tc, test_overloading_mixed_param_types());
unittest_test_case_add_result(tc, test_overloading_three_overloads());
unittest_test_suite_add_test_case(suite, tc);
unittest_generate_report(suite, config);
int failures = suite->total_failed + suite->total_errors;
unittest_test_suite_destroy(suite);
unittest_config_destroy(config);
return failures > 0 ? 1 : 0;
}

View File

@ -0,0 +1,100 @@
#include "test_utils.h"
UnittestTestResult_t* test_overloading_call_two_params(void) {
UNITTEST_BEGIN_TEST("TestOverloadingRuntime", "test_call_two_params");
const char* source =
"public class Calculator {\n"
" public static int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"\n"
" public static int add(int a, int b, int c) {\n"
" return a + b + c;\n"
" }\n"
"\n"
" public static int main() {\n"
" return add(10, 20);\n"
" }\n"
"}\n";
RAVA_TEST_RUN(_unittest_result, source, "Calculator", "main", 30,
"add(10, 20) should return 30");
UNITTEST_END_TEST();
}
UnittestTestResult_t* test_overloading_call_three_params(void) {
UNITTEST_BEGIN_TEST("TestOverloadingRuntime", "test_call_three_params");
const char* source =
"public class Calculator {\n"
" public static int add(int a, int b) {\n"
" return a + b;\n"
" }\n"
"\n"
" public static int add(int a, int b, int c) {\n"
" return a + b + c;\n"
" }\n"
"\n"
" public static int main() {\n"
" return add(10, 20, 30);\n"
" }\n"
"}\n";
RAVA_TEST_RUN(_unittest_result, source, "Calculator", "main", 60,
"add(10, 20, 30) should return 60");
UNITTEST_END_TEST();
}
UnittestTestResult_t* test_overloading_different_types(void) {
UNITTEST_BEGIN_TEST("TestOverloadingRuntime", "test_different_types");
const char* source =
"public class Math {\n"
" public static int max(int a, int b) {\n"
" return a > b ? a : b;\n"
" }\n"
"\n"
" public static double max(double a, double b) {\n"
" return a > b ? a : b;\n"
" }\n"
"\n"
" public static int main() {\n"
" return max(15, 25);\n"
" }\n"
"}\n";
RAVA_TEST_RUN(_unittest_result, source, "Math", "main", 25,
"max(15, 25) should return 25");
UNITTEST_END_TEST();
}
int main(int argc, char **argv) {
UnittestConfig_t *config = unittest_config_create();
config->verbosity = 2;
config->track_execution_time = true;
if (argc > 1 && strcmp(argv[1], "--json") == 0) {
config->output_format = UNITTEST_FORMAT_JSON;
config->use_colors = false;
}
UnittestTestSuite_t *suite = unittest_test_suite_create("Method Overloading Runtime Tests");
UnittestTestCase_t *tc = unittest_test_case_create("TestOverloadingRuntime");
unittest_test_case_add_result(tc, test_overloading_call_two_params());
unittest_test_case_add_result(tc, test_overloading_call_three_params());
unittest_test_case_add_result(tc, test_overloading_different_types());
unittest_test_suite_add_test_case(suite, tc);
unittest_generate_report(suite, config);
int failures = suite->total_failed + suite->total_errors;
unittest_test_suite_destroy(suite);
unittest_config_destroy(config);
return failures > 0 ? 1 : 0;
}

View File

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

View File

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

View File

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

View File

@ -19,14 +19,4 @@ static inline void* rava_safe_realloc(void *ptr, size_t size) {
return new_ptr;
}
static inline void* rava_safe_malloc(size_t size) {
if (size == 0) return NULL;
return malloc(size);
}
static inline void* rava_safe_calloc(size_t count, size_t size) {
if (count == 0 || size == 0) return NULL;
return calloc(count, size);
}
#endif