Compare commits
No commits in common. "44126e4ac0553fb118baad0c30324d1b80db7bea" and "3872c529976a6a36444e207b0db7d0ce306b5ff6" have entirely different histories.
44126e4ac0
...
3872c52997
91
Makefile
91
Makefile
@ -1,6 +1,6 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -Werror -std=gnu99 -O3 -march=native -I.
|
||||
LDFLAGS = -ldl -lm
|
||||
LDFLAGS = -ldl
|
||||
|
||||
LEXER_SOURCES = lexer/lexer_tokenizer.c lexer/lexer_keywords.c lexer/lexer_literals.c
|
||||
LEXER_OBJECTS = $(LEXER_SOURCES:.c=.o)
|
||||
@ -53,43 +53,7 @@ TEST_INSTANCE_OBJECTS = $(TEST_INSTANCE_SOURCES:.c=.o)
|
||||
TEST_FILEIO_SOURCES = tests/test_fileio.c
|
||||
TEST_FILEIO_OBJECTS = $(TEST_FILEIO_SOURCES:.c=.o)
|
||||
|
||||
TEST_DOWHILE_SOURCES = tests/test_dowhile.c
|
||||
TEST_DOWHILE_OBJECTS = $(TEST_DOWHILE_SOURCES:.c=.o)
|
||||
|
||||
TEST_SWITCH_SOURCES = tests/test_switch.c
|
||||
TEST_SWITCH_OBJECTS = $(TEST_SWITCH_SOURCES:.c=.o)
|
||||
|
||||
TEST_MATH_SOURCES = tests/test_math.c
|
||||
TEST_MATH_OBJECTS = $(TEST_MATH_SOURCES:.c=.o)
|
||||
|
||||
TEST_STRING_METHODS_SOURCES = tests/test_string_methods.c
|
||||
TEST_STRING_METHODS_OBJECTS = $(TEST_STRING_METHODS_SOURCES:.c=.o)
|
||||
|
||||
TEST_STATIC_SOURCES = tests/test_static.c
|
||||
TEST_STATIC_OBJECTS = $(TEST_STATIC_SOURCES:.c=.o)
|
||||
|
||||
TEST_INTERFACES_SOURCES = tests/test_interfaces.c
|
||||
TEST_INTERFACES_OBJECTS = $(TEST_INTERFACES_SOURCES:.c=.o)
|
||||
|
||||
TEST_EXCEPTIONS_SOURCES = tests/test_exceptions.c
|
||||
TEST_EXCEPTIONS_OBJECTS = $(TEST_EXCEPTIONS_SOURCES:.c=.o)
|
||||
|
||||
TEST_TERNARY_SOURCES = tests/test_ternary.c
|
||||
TEST_TERNARY_OBJECTS = $(TEST_TERNARY_SOURCES:.c=.o)
|
||||
|
||||
TEST_BITWISE_SOURCES = tests/test_bitwise.c
|
||||
TEST_BITWISE_OBJECTS = $(TEST_BITWISE_SOURCES:.c=.o)
|
||||
|
||||
TEST_ENHANCED_FOR_SOURCES = tests/test_enhanced_for.c
|
||||
TEST_ENHANCED_FOR_OBJECTS = $(TEST_ENHANCED_FOR_SOURCES:.c=.o)
|
||||
|
||||
TEST_ARRAY_INIT_SOURCES = tests/test_array_init.c
|
||||
TEST_ARRAY_INIT_OBJECTS = $(TEST_ARRAY_INIT_SOURCES:.c=.o)
|
||||
|
||||
TEST_INSTANCEOF_SOURCES = tests/test_instanceof.c
|
||||
TEST_INSTANCEOF_OBJECTS = $(TEST_INSTANCEOF_SOURCES:.c=.o)
|
||||
|
||||
all: 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
|
||||
all: test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio
|
||||
|
||||
test_lexer: $(LEXER_OBJECTS) $(TEST_LEXER_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
@ -121,42 +85,6 @@ test_instance_methods: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEM
|
||||
test_fileio: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_FILEIO_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_dowhile: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_DOWHILE_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_switch: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_SWITCH_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_math: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_MATH_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_string_methods: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_STRING_METHODS_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_static: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_STATIC_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_interfaces: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_INTERFACES_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_exceptions: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_EXCEPTIONS_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_ternary: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_TERNARY_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_bitwise: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_BITWISE_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_enhanced_for: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_ENHANCED_FOR_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_array_init: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_ARRAY_INIT_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_instanceof: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_INSTANCEOF_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
@ -222,17 +150,8 @@ clean:
|
||||
$(PHASE0_OBJECTS) \
|
||||
$(TEST_LEXER_OBJECTS) $(TEST_PARSER_OBJECTS) $(TEST_SEMANTIC_OBJECTS) $(TEST_IR_OBJECTS) $(TEST_RUNTIME_OBJECTS) \
|
||||
$(TEST_STRINGS_OBJECTS) $(TEST_ARRAYS_OBJECTS) $(TEST_OBJECTS_OBJECTS) $(TEST_INSTANCE_OBJECTS) $(TEST_FILEIO_OBJECTS) \
|
||||
$(TEST_DOWHILE_OBJECTS) $(TEST_SWITCH_OBJECTS) $(TEST_MATH_OBJECTS) $(TEST_STRING_METHODS_OBJECTS) $(TEST_STATIC_OBJECTS) $(TEST_INTERFACES_OBJECTS) $(TEST_EXCEPTIONS_OBJECTS) $(TEST_TERNARY_OBJECTS) $(TEST_BITWISE_OBJECTS) $(TEST_ENHANCED_FOR_OBJECTS) $(TEST_ARRAY_INIT_OBJECTS) $(TEST_INSTANCEOF_OBJECTS) $(TEST_BENCHMARK_OBJECTS) \
|
||||
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_benchmark \
|
||||
$(TEST_BENCHMARK_OBJECTS) \
|
||||
test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio test_benchmark \
|
||||
test_nanbox test_fastframe test_labeltable test_methodcache test_benchmark_pgo *.gcda */*.gcda
|
||||
|
||||
.PHONY: all clean benchmark test_phase0 pgo test_benchmark_pgo_gen pgo_run test_benchmark_pgo test
|
||||
|
||||
test: all
|
||||
@echo "=== Running All Tests ==="
|
||||
@./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 && \
|
||||
echo "" && echo "=== All Tests Passed ==="
|
||||
.PHONY: all clean benchmark test_phase0 pgo test_benchmark_pgo_gen pgo_run test_benchmark_pgo
|
||||
|
||||
15
README.md
15
README.md
@ -17,13 +17,10 @@ The pipeline:
|
||||
|
||||
Supported features:
|
||||
- Primitives: int, long, double, boolean, char
|
||||
- Arrays, strings, and array initializers
|
||||
- Objects, instance methods, and instanceof
|
||||
- Inheritance and interfaces
|
||||
- Control flow: if/else, while, do-while, for, enhanced for-each, switch/case, break, continue
|
||||
- Operators: arithmetic, bitwise (AND, OR, XOR, shifts), ternary (? :)
|
||||
- Exception handling: try/catch/finally, throw
|
||||
- Math functions and String methods
|
||||
- Arrays and strings
|
||||
- Objects and instance methods
|
||||
- Inheritance
|
||||
- Control flow: if/else, while, for, break, continue
|
||||
- File I/O
|
||||
- Recursion
|
||||
- System.out.println
|
||||
@ -62,10 +59,10 @@ Run the benchmark:
|
||||
make benchmark
|
||||
```
|
||||
|
||||
Run all tests:
|
||||
Run tests:
|
||||
|
||||
```bash
|
||||
make test
|
||||
make test_runtime && ./test_runtime
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
public class DoWhile {
|
||||
public static int main() {
|
||||
int i = 0;
|
||||
int sum = 0;
|
||||
|
||||
do {
|
||||
sum = sum + i;
|
||||
i = i + 1;
|
||||
} while (i < 5);
|
||||
|
||||
System.out.println(sum);
|
||||
|
||||
int j = 10;
|
||||
do {
|
||||
System.out.println(j);
|
||||
j = j - 1;
|
||||
} while (j > 7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
33
ir/ir.h
33
ir/ir.h
@ -53,7 +53,6 @@ typedef enum {
|
||||
RAVA_OP_CALL,
|
||||
RAVA_OP_CALL_STATIC,
|
||||
RAVA_OP_CALL_VIRTUAL,
|
||||
RAVA_OP_CALL_SUPER,
|
||||
RAVA_OP_CALL_NATIVE,
|
||||
RAVA_OP_RETURN,
|
||||
RAVA_OP_RETURN_VOID,
|
||||
@ -68,8 +67,6 @@ typedef enum {
|
||||
RAVA_OP_INSTANCEOF,
|
||||
|
||||
RAVA_OP_THROW,
|
||||
RAVA_OP_TRY_BEGIN,
|
||||
RAVA_OP_TRY_END,
|
||||
RAVA_OP_POP,
|
||||
RAVA_OP_DUP,
|
||||
|
||||
@ -81,13 +78,6 @@ typedef enum {
|
||||
RAVA_OP_STRING_SUBSTRING,
|
||||
RAVA_OP_STRING_EQUALS,
|
||||
RAVA_OP_STRING_COMPARETO,
|
||||
RAVA_OP_STRING_INDEXOF,
|
||||
RAVA_OP_STRING_CONTAINS,
|
||||
RAVA_OP_STRING_STARTSWITH,
|
||||
RAVA_OP_STRING_ENDSWITH,
|
||||
RAVA_OP_STRING_TOLOWERCASE,
|
||||
RAVA_OP_STRING_TOUPPERCASE,
|
||||
RAVA_OP_STRING_TRIM,
|
||||
|
||||
RAVA_OP_LOAD_THIS,
|
||||
|
||||
@ -106,22 +96,7 @@ typedef enum {
|
||||
RAVA_OP_LOAD_LOCAL_CONST_LE_JUMPFALSE,
|
||||
RAVA_OP_LOAD_TWO_LOCALS,
|
||||
RAVA_OP_ADD_LOCAL_TO_LOCAL,
|
||||
RAVA_OP_LOAD_LOCAL_LT_LOCAL_JUMPFALSE,
|
||||
|
||||
RAVA_OP_MATH_ABS,
|
||||
RAVA_OP_MATH_SQRT,
|
||||
RAVA_OP_MATH_POW,
|
||||
RAVA_OP_MATH_MIN,
|
||||
RAVA_OP_MATH_MAX,
|
||||
RAVA_OP_MATH_FLOOR,
|
||||
RAVA_OP_MATH_CEIL,
|
||||
RAVA_OP_MATH_ROUND,
|
||||
RAVA_OP_MATH_SIN,
|
||||
RAVA_OP_MATH_COS,
|
||||
RAVA_OP_MATH_TAN,
|
||||
RAVA_OP_MATH_LOG,
|
||||
RAVA_OP_MATH_EXP,
|
||||
RAVA_OP_MATH_RANDOM
|
||||
RAVA_OP_LOAD_LOCAL_LT_LOCAL_JUMPFALSE
|
||||
} RavaOpCode_e;
|
||||
|
||||
typedef union {
|
||||
@ -160,12 +135,6 @@ typedef union {
|
||||
int local2;
|
||||
int label_id;
|
||||
} cmp_locals;
|
||||
struct {
|
||||
int catch_label;
|
||||
int finally_label;
|
||||
int end_label;
|
||||
int exception_local;
|
||||
} try_handler;
|
||||
} RavaOperand_u;
|
||||
|
||||
typedef struct {
|
||||
|
||||
565
ir/ir_gen.c
565
ir/ir_gen.c
@ -35,15 +35,6 @@ static int _rava_ir_find_local(RavaIRGenerator_t *gen, const char *name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool _rava_ir_is_class_name(RavaIRGenerator_t *gen, const char *name) {
|
||||
for (size_t i = 0; i < gen->program->class_count; i++) {
|
||||
if (strcmp(gen->program->classes[i]->name, name) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RavaIRGenerator_t* rava_ir_generator_create(RavaSemanticAnalyzer_t *analyzer) {
|
||||
RavaIRGenerator_t *gen = calloc(1, sizeof(RavaIRGenerator_t));
|
||||
gen->program = rava_program_create();
|
||||
@ -91,12 +82,6 @@ static void _rava_ir_gen_binary_expr(RavaIRGenerator_t *gen, RavaASTNode_t *expr
|
||||
case RAVA_BINOP_GE: instr.opcode = RAVA_OP_GE; break;
|
||||
case RAVA_BINOP_AND: instr.opcode = RAVA_OP_AND; break;
|
||||
case RAVA_BINOP_OR: instr.opcode = RAVA_OP_OR; break;
|
||||
case RAVA_BINOP_BITAND: instr.opcode = RAVA_OP_AND; break;
|
||||
case RAVA_BINOP_BITOR: instr.opcode = RAVA_OP_OR; break;
|
||||
case RAVA_BINOP_BITXOR: instr.opcode = RAVA_OP_XOR; break;
|
||||
case RAVA_BINOP_LSHIFT: instr.opcode = RAVA_OP_SHL; break;
|
||||
case RAVA_BINOP_RSHIFT: instr.opcode = RAVA_OP_SHR; break;
|
||||
case RAVA_BINOP_URSHIFT: instr.opcode = RAVA_OP_USHR; break;
|
||||
default: instr.opcode = RAVA_OP_NOP; break;
|
||||
}
|
||||
|
||||
@ -205,19 +190,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
instr.opcode = RAVA_OP_STORE_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (expr->data.assign.target->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||
RavaASTNode_t *target_member = expr->data.assign.target;
|
||||
if (target_member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR) {
|
||||
const char *obj_name = target_member->data.member_access.object->data.identifier.name;
|
||||
if (_rava_ir_is_class_name(gen, obj_name) ||
|
||||
strcmp(obj_name, gen->current_class->name) == 0) {
|
||||
_rava_ir_gen_expression(gen, expr->data.assign.value);
|
||||
instr.opcode = RAVA_OP_STORE_STATIC;
|
||||
instr.operand.field.class_name = strdup(obj_name);
|
||||
instr.operand.field.field_name = strdup(target_member->data.member_access.member);
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_rava_ir_gen_expression(gen, expr->data.assign.target->data.member_access.object);
|
||||
_rava_ir_gen_expression(gen, expr->data.assign.value);
|
||||
instr.opcode = RAVA_OP_PUT_FIELD;
|
||||
@ -238,17 +210,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
break;
|
||||
|
||||
case RAVA_AST_MEMBER_ACCESS_EXPR:
|
||||
if (expr->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR) {
|
||||
const char *obj_name = expr->data.member_access.object->data.identifier.name;
|
||||
if (_rava_ir_is_class_name(gen, obj_name) ||
|
||||
strcmp(obj_name, gen->current_class->name) == 0) {
|
||||
instr.opcode = RAVA_OP_LOAD_STATIC;
|
||||
instr.operand.field.class_name = strdup(obj_name);
|
||||
instr.operand.field.field_name = strdup(expr->data.member_access.member);
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_rava_ir_gen_expression(gen, expr->data.member_access.object);
|
||||
instr.opcode = RAVA_OP_GET_FIELD;
|
||||
instr.operand.field.field_name = strdup(expr->data.member_access.member);
|
||||
@ -290,36 +251,13 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
bool is_print = false;
|
||||
bool is_string_length = false;
|
||||
bool is_string_charat = false;
|
||||
bool is_string_substring = false;
|
||||
bool is_string_equals = false;
|
||||
bool is_string_compareto = false;
|
||||
bool is_string_indexof = false;
|
||||
bool is_string_contains = false;
|
||||
bool is_string_startswith = false;
|
||||
bool is_string_endswith = false;
|
||||
bool is_string_tolowercase = false;
|
||||
bool is_string_touppercase = false;
|
||||
bool is_string_trim = false;
|
||||
bool is_file_read = false;
|
||||
bool is_file_write = false;
|
||||
bool is_file_exists = false;
|
||||
bool is_file_delete = false;
|
||||
bool is_current_time_millis = false;
|
||||
bool is_nano_time = false;
|
||||
bool is_math_abs = false;
|
||||
bool is_math_sqrt = false;
|
||||
bool is_math_pow = false;
|
||||
bool is_math_min = false;
|
||||
bool is_math_max = false;
|
||||
bool is_math_floor = false;
|
||||
bool is_math_ceil = false;
|
||||
bool is_math_round = false;
|
||||
bool is_math_sin = false;
|
||||
bool is_math_cos = false;
|
||||
bool is_math_tan = false;
|
||||
bool is_math_log = false;
|
||||
bool is_math_exp = false;
|
||||
bool is_math_random = false;
|
||||
RavaASTNode_t *string_object = NULL;
|
||||
|
||||
if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||
@ -356,39 +294,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
is_file_delete = true;
|
||||
}
|
||||
}
|
||||
if (member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR &&
|
||||
strcmp(member->data.member_access.object->data.identifier.name, "Math") == 0) {
|
||||
const char *method = member->data.member_access.member;
|
||||
if (strcmp(method, "abs") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_abs = true;
|
||||
} else if (strcmp(method, "sqrt") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_sqrt = true;
|
||||
} else if (strcmp(method, "pow") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_math_pow = true;
|
||||
} else if (strcmp(method, "min") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_math_min = true;
|
||||
} else if (strcmp(method, "max") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_math_max = true;
|
||||
} else if (strcmp(method, "floor") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_floor = true;
|
||||
} else if (strcmp(method, "ceil") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_ceil = true;
|
||||
} else if (strcmp(method, "round") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_round = true;
|
||||
} else if (strcmp(method, "sin") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_sin = true;
|
||||
} else if (strcmp(method, "cos") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_cos = true;
|
||||
} else if (strcmp(method, "tan") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_tan = true;
|
||||
} else if (strcmp(method, "log") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_log = true;
|
||||
} else if (strcmp(method, "exp") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_exp = true;
|
||||
} else if (strcmp(method, "random") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_math_random = true;
|
||||
}
|
||||
}
|
||||
if (strcmp(member->data.member_access.member, "length") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_length = true;
|
||||
string_object = member->data.member_access.object;
|
||||
@ -398,33 +303,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
} else if (strcmp(member->data.member_access.member, "equals") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_equals = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "substring") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_string_substring = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "compareTo") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_compareto = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "indexOf") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_indexof = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "contains") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_contains = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "startsWith") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_startswith = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "endsWith") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_endswith = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "toLowerCase") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_tolowercase = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "toUpperCase") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_touppercase = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "trim") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_trim = true;
|
||||
string_object = member->data.member_access.object;
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,107 +343,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_EQUALS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_substring) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_STRING_SUBSTRING;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_compareto) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_COMPARETO;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_indexof) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_INDEXOF;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_contains) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_CONTAINS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_startswith) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_STARTSWITH;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_endswith) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_ENDSWITH;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_tolowercase) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
instr.opcode = RAVA_OP_STRING_TOLOWERCASE;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_touppercase) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
instr.opcode = RAVA_OP_STRING_TOUPPERCASE;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_trim) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
instr.opcode = RAVA_OP_STRING_TRIM;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_abs) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_ABS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_sqrt) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_SQRT;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_pow) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_MATH_POW;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_min) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_MATH_MIN;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_max) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_MATH_MAX;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_floor) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_FLOOR;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_ceil) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_CEIL;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_round) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_ROUND;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_sin) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_SIN;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_cos) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_COS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_tan) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_TAN;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_log) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_LOG;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_exp) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_EXP;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_random) {
|
||||
instr.opcode = RAVA_OP_MATH_RANDOM;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_println || is_print) {
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
@ -578,28 +355,15 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||
RavaASTNode_t *member = expr->data.call.callee;
|
||||
if (member->data.member_access.object->type == RAVA_AST_SUPER_EXPR) {
|
||||
instr.opcode = RAVA_OP_LOAD_THIS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
}
|
||||
instr.opcode = RAVA_OP_CALL_SUPER;
|
||||
instr.operand.call.class_name = gen->current_class->superclass ? strdup(gen->current_class->superclass) : NULL;
|
||||
instr.operand.call.method_name = strdup(member->data.member_access.member);
|
||||
instr.operand.call.arg_count = expr->data.call.arguments_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
_rava_ir_gen_expression(gen, member->data.member_access.object);
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
}
|
||||
instr.opcode = RAVA_OP_CALL_VIRTUAL;
|
||||
instr.operand.call.class_name = strdup(gen->current_class->name);
|
||||
instr.operand.call.method_name = strdup(member->data.member_access.member);
|
||||
instr.operand.call.arg_count = expr->data.call.arguments_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
_rava_ir_gen_expression(gen, member->data.member_access.object);
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
}
|
||||
instr.opcode = RAVA_OP_CALL_VIRTUAL;
|
||||
instr.operand.call.class_name = strdup(gen->current_class->name);
|
||||
instr.operand.call.method_name = strdup(member->data.member_access.member);
|
||||
instr.operand.call.arg_count = expr->data.call.arguments_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
@ -620,74 +384,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
case RAVA_AST_CAST_EXPR:
|
||||
_rava_ir_gen_expression(gen, expr->data.cast.expression);
|
||||
instr.opcode = RAVA_OP_CAST;
|
||||
if (expr->data.cast.type && expr->data.cast.type->data.type.type_name) {
|
||||
instr.operand.var.type = rava_type_from_name(expr->data.cast.type->data.type.type_name);
|
||||
}
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
case RAVA_AST_TERNARY_EXPR: {
|
||||
_rava_ir_gen_expression(gen, expr->data.ternary.condition);
|
||||
|
||||
int else_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP_IF_FALSE;
|
||||
instr.operand.label_id = else_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, expr->data.ternary.true_expr);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = else_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, expr->data.ternary.false_expr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_ARRAY_INIT_EXPR: {
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = (int)expr->data.array_init.elements_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_NEW_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
for (size_t i = 0; i < expr->data.array_init.elements_count; i++) {
|
||||
instr.opcode = RAVA_OP_DUP;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = (int)i;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, expr->data.array_init.elements[i]);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_INSTANCEOF_EXPR:
|
||||
_rava_ir_gen_expression(gen, expr->data.instanceof_expr.expression);
|
||||
instr.opcode = RAVA_OP_INSTANCEOF;
|
||||
instr.operand.string_value = strdup(expr->data.instanceof_expr.type_name);
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -767,33 +463,6 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_DO_WHILE_STMT: {
|
||||
int start_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = start_label, .parent = gen->loop_context };
|
||||
gen->loop_context = &loop_ctx;
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.while_stmt.body);
|
||||
|
||||
_rava_ir_gen_expression(gen, stmt->data.while_stmt.condition);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP_IF_TRUE;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
gen->loop_context = loop_ctx.parent;
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_FOR_STMT: {
|
||||
if (stmt->data.for_stmt.init) {
|
||||
if (stmt->data.for_stmt.init->type == RAVA_AST_VAR_DECL) {
|
||||
@ -847,93 +516,6 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_ENHANCED_FOR_STMT: {
|
||||
size_t idx_local = gen->next_local++;
|
||||
size_t elem_local = gen->next_local++;
|
||||
gen->current_method->local_count = gen->next_local;
|
||||
|
||||
_rava_ir_add_local(gen, stmt->data.enhanced_for.var_name, elem_local);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = 0;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
int start_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int continue_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = continue_label, .parent = gen->loop_context };
|
||||
gen->loop_context = &loop_ctx;
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, stmt->data.enhanced_for.iterable);
|
||||
instr.opcode = RAVA_OP_ARRAY_LENGTH;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LT;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP_IF_FALSE;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, stmt->data.enhanced_for.iterable);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_LOCAL;
|
||||
instr.operand.var.index = elem_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.enhanced_for.body);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = continue_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = 1;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_ADD;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
gen->loop_context = loop_ctx.parent;
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_RETURN_STMT:
|
||||
if (stmt->data.return_stmt.value) {
|
||||
_rava_ir_gen_expression(gen, stmt->data.return_stmt.value);
|
||||
@ -964,67 +546,6 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_SWITCH_STMT: {
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
RavaLoopContext_t switch_ctx = { .break_label = end_label, .continue_label = -1, .parent = gen->loop_context };
|
||||
gen->loop_context = &switch_ctx;
|
||||
|
||||
size_t case_count = stmt->children_count;
|
||||
int *case_labels = malloc(case_count * sizeof(int));
|
||||
int default_label = -1;
|
||||
|
||||
for (size_t i = 0; i < case_count; i++) {
|
||||
case_labels[i] = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
if (stmt->children[i]->data.case_stmt.is_default) {
|
||||
default_label = case_labels[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < case_count; i++) {
|
||||
RavaASTNode_t *case_node = stmt->children[i];
|
||||
if (!case_node->data.case_stmt.is_default) {
|
||||
_rava_ir_gen_expression(gen, stmt->data.switch_stmt.expression);
|
||||
_rava_ir_gen_expression(gen, case_node->data.case_stmt.value);
|
||||
instr.opcode = RAVA_OP_EQ;
|
||||
_rava_ir_emit(gen, instr);
|
||||
instr.opcode = RAVA_OP_JUMP_IF_TRUE;
|
||||
instr.operand.label_id = case_labels[i];
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
}
|
||||
|
||||
if (default_label >= 0) {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = default_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < case_count; i++) {
|
||||
RavaASTNode_t *case_node = stmt->children[i];
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = case_labels[i];
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
for (size_t j = 0; j < case_node->children_count; j++) {
|
||||
_rava_ir_gen_statement(gen, case_node->children[j]);
|
||||
}
|
||||
}
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
free(case_labels);
|
||||
gen->loop_context = switch_ctx.parent;
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_BREAK_STMT:
|
||||
if (gen->loop_context) {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
@ -1041,76 +562,6 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
}
|
||||
break;
|
||||
|
||||
case RAVA_AST_THROW_STMT:
|
||||
if (stmt->data.throw_stmt.expression) {
|
||||
_rava_ir_gen_expression(gen, stmt->data.throw_stmt.expression);
|
||||
} else {
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = 1;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
instr.opcode = RAVA_OP_THROW;
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
case RAVA_AST_TRY_STMT: {
|
||||
int catch_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int finally_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
int exception_local = gen->next_local++;
|
||||
gen->current_method->local_count = gen->next_local;
|
||||
|
||||
instr.opcode = RAVA_OP_TRY_BEGIN;
|
||||
instr.operand.try_handler.catch_label = catch_label;
|
||||
instr.operand.try_handler.finally_label = stmt->data.try_stmt.finally_block ? finally_label : -1;
|
||||
instr.operand.try_handler.end_label = end_label;
|
||||
instr.operand.try_handler.exception_local = exception_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.try_stmt.try_block);
|
||||
|
||||
instr.opcode = RAVA_OP_TRY_END;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
if (stmt->data.try_stmt.finally_block) {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = finally_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = catch_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
for (size_t i = 0; i < stmt->data.try_stmt.catch_count; i++) {
|
||||
RavaASTNode_t *catch_node = stmt->data.try_stmt.catch_clauses[i];
|
||||
|
||||
if (catch_node->data.catch_clause.exception_name) {
|
||||
_rava_ir_add_local(gen, catch_node->data.catch_clause.exception_name, exception_local);
|
||||
}
|
||||
|
||||
_rava_ir_gen_statement(gen, catch_node->data.catch_clause.body);
|
||||
}
|
||||
|
||||
if (stmt->data.try_stmt.finally_block) {
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = finally_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.try_stmt.finally_block);
|
||||
}
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -157,19 +157,11 @@ struct RavaASTNode_t {
|
||||
struct {
|
||||
char *name;
|
||||
char *superclass;
|
||||
char **interfaces;
|
||||
size_t interfaces_count;
|
||||
RavaASTNode_t *type;
|
||||
RavaModifier_e *modifiers;
|
||||
size_t modifiers_count;
|
||||
} class_decl;
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
RavaModifier_e *modifiers;
|
||||
size_t modifiers_count;
|
||||
} interface_decl;
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
RavaASTNode_t *return_type;
|
||||
@ -183,14 +175,6 @@ struct RavaASTNode_t {
|
||||
RavaASTNode_t *initializer;
|
||||
} var_decl;
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
RavaASTNode_t *type;
|
||||
RavaASTNode_t *initializer;
|
||||
RavaModifier_e *modifiers;
|
||||
size_t modifiers_count;
|
||||
} field_decl;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *condition;
|
||||
RavaASTNode_t *then_stmt;
|
||||
@ -209,13 +193,6 @@ struct RavaASTNode_t {
|
||||
RavaASTNode_t *body;
|
||||
} for_stmt;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *var_type;
|
||||
char *var_name;
|
||||
RavaASTNode_t *iterable;
|
||||
RavaASTNode_t *body;
|
||||
} enhanced_for;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *value;
|
||||
} return_stmt;
|
||||
@ -252,42 +229,6 @@ struct RavaASTNode_t {
|
||||
RavaASTNode_t *type;
|
||||
RavaASTNode_t *expression;
|
||||
} cast;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *expression;
|
||||
} switch_stmt;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *value;
|
||||
bool is_default;
|
||||
} case_stmt;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *try_block;
|
||||
RavaASTNode_t **catch_clauses;
|
||||
size_t catch_count;
|
||||
RavaASTNode_t *finally_block;
|
||||
} try_stmt;
|
||||
|
||||
struct {
|
||||
char *exception_type;
|
||||
char *exception_name;
|
||||
RavaASTNode_t *body;
|
||||
} catch_clause;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *expression;
|
||||
} throw_stmt;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t **elements;
|
||||
size_t elements_count;
|
||||
} array_init;
|
||||
|
||||
struct {
|
||||
RavaASTNode_t *expression;
|
||||
char *type_name;
|
||||
} instanceof_expr;
|
||||
} data;
|
||||
};
|
||||
|
||||
|
||||
@ -78,8 +78,6 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
|
||||
class_decl->data.class_decl.modifiers = modifiers;
|
||||
class_decl->data.class_decl.modifiers_count = modifiers_count;
|
||||
class_decl->data.class_decl.superclass = NULL;
|
||||
class_decl->data.class_decl.interfaces = NULL;
|
||||
class_decl->data.class_decl.interfaces_count = 0;
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
class_decl->data.class_decl.name = strdup(parser->current_token->lexeme);
|
||||
@ -93,24 +91,6 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
|
||||
}
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_IMPLEMENTS)) {
|
||||
size_t capacity = 4;
|
||||
class_decl->data.class_decl.interfaces = malloc(capacity * sizeof(char*));
|
||||
do {
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
if (class_decl->data.class_decl.interfaces_count >= capacity) {
|
||||
capacity *= 2;
|
||||
class_decl->data.class_decl.interfaces = realloc(
|
||||
class_decl->data.class_decl.interfaces,
|
||||
capacity * sizeof(char*));
|
||||
}
|
||||
class_decl->data.class_decl.interfaces[class_decl->data.class_decl.interfaces_count++] =
|
||||
strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
} while (_rava_parser_match(parser, RAVA_TOKEN_COMMA));
|
||||
}
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after class name");
|
||||
|
||||
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
||||
@ -180,18 +160,15 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
|
||||
RavaASTNode_t *field = rava_ast_node_create(RAVA_AST_FIELD_DECL,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
field->data.field_decl.type = member_type;
|
||||
field->data.field_decl.name = name;
|
||||
field->data.field_decl.modifiers = member_modifiers;
|
||||
field->data.field_decl.modifiers_count = member_modifiers_count;
|
||||
field->data.var_decl.type = member_type;
|
||||
field->data.var_decl.name = name;
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||
field->data.field_decl.initializer = _rava_parser_parse_expression(parser);
|
||||
field->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
field->data.field_decl.initializer = NULL;
|
||||
field->data.var_decl.initializer = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after field declaration");
|
||||
rava_ast_node_add_child(class_decl, field);
|
||||
member_modifiers = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,63 +178,6 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
|
||||
return class_decl;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_interface_declaration(RavaParser_t *parser) {
|
||||
RavaModifier_e *modifiers = NULL;
|
||||
size_t modifiers_count = 0;
|
||||
|
||||
_rava_parser_parse_modifiers(parser, &modifiers, &modifiers_count);
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_KEYWORD_INTERFACE, "Expected 'interface' keyword");
|
||||
|
||||
RavaASTNode_t *interface_decl = rava_ast_node_create(RAVA_AST_INTERFACE_DECL,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
|
||||
interface_decl->data.interface_decl.modifiers = modifiers;
|
||||
interface_decl->data.interface_decl.modifiers_count = modifiers_count;
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
interface_decl->data.interface_decl.name = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after interface name");
|
||||
|
||||
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
||||
|
||||
RavaModifier_e *member_modifiers = NULL;
|
||||
size_t member_modifiers_count = 0;
|
||||
|
||||
_rava_parser_parse_modifiers(parser, &member_modifiers, &member_modifiers_count);
|
||||
|
||||
RavaASTNode_t *member_type = _rava_parser_parse_type(parser);
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
char *name = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_LPAREN)) {
|
||||
RavaASTNode_t *method = _rava_parser_parse_method_declaration(parser,
|
||||
member_modifiers,
|
||||
member_modifiers_count,
|
||||
member_type);
|
||||
method->data.method_decl.name = name;
|
||||
rava_ast_node_add_child(interface_decl, method);
|
||||
} else {
|
||||
free(name);
|
||||
free(member_modifiers);
|
||||
}
|
||||
} else {
|
||||
free(member_modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' after interface body");
|
||||
|
||||
return interface_decl;
|
||||
}
|
||||
|
||||
RavaASTNode_t* rava_parser_parse(RavaParser_t *parser) {
|
||||
RavaASTNode_t *root = rava_ast_node_create(RAVA_AST_COMPILATION_UNIT, 1, 1);
|
||||
|
||||
@ -266,27 +186,7 @@ RavaASTNode_t* rava_parser_parse(RavaParser_t *parser) {
|
||||
break;
|
||||
}
|
||||
|
||||
RavaModifier_e *modifiers = NULL;
|
||||
size_t modifiers_count = 0;
|
||||
_rava_parser_parse_modifiers(parser, &modifiers, &modifiers_count);
|
||||
|
||||
RavaASTNode_t *decl = NULL;
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INTERFACE)) {
|
||||
RavaToken_t *saved = parser->current_token;
|
||||
parser->current_token = saved;
|
||||
free(modifiers);
|
||||
decl = _rava_parser_parse_interface_declaration(parser);
|
||||
} else if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CLASS)) {
|
||||
RavaToken_t *saved = parser->current_token;
|
||||
parser->current_token = saved;
|
||||
free(modifiers);
|
||||
decl = _rava_parser_parse_class_declaration(parser);
|
||||
} else {
|
||||
free(modifiers);
|
||||
break;
|
||||
}
|
||||
|
||||
RavaASTNode_t *decl = _rava_parser_parse_class_declaration(parser);
|
||||
if (decl) {
|
||||
rava_ast_node_add_child(root, decl);
|
||||
}
|
||||
|
||||
@ -10,19 +10,6 @@ extern bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, cons
|
||||
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
|
||||
|
||||
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
|
||||
RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser);
|
||||
static RavaASTNode_t* _rava_parser_parse_unary(RavaParser_t *parser);
|
||||
|
||||
static bool _is_primitive_type_token(RavaTokenType_e type) {
|
||||
return type == RAVA_TOKEN_KEYWORD_INT ||
|
||||
type == RAVA_TOKEN_KEYWORD_LONG ||
|
||||
type == RAVA_TOKEN_KEYWORD_DOUBLE ||
|
||||
type == RAVA_TOKEN_KEYWORD_FLOAT ||
|
||||
type == RAVA_TOKEN_KEYWORD_BOOLEAN ||
|
||||
type == RAVA_TOKEN_KEYWORD_CHAR ||
|
||||
type == RAVA_TOKEN_KEYWORD_BYTE ||
|
||||
type == RAVA_TOKEN_KEYWORD_SHORT;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
|
||||
RavaASTNode_t *node = NULL;
|
||||
@ -73,16 +60,6 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_LPAREN)) {
|
||||
if (_is_primitive_type_token(parser->current_token->type) &&
|
||||
parser->peek_token && parser->peek_token->type == RAVA_TOKEN_RPAREN) {
|
||||
RavaASTNode_t *cast_node = rava_ast_node_create(RAVA_AST_CAST_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
cast_node->data.cast.type = _rava_parser_parse_type(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after type in cast");
|
||||
cast_node->data.cast.expression = _rava_parser_parse_unary(parser);
|
||||
return cast_node;
|
||||
}
|
||||
RavaASTNode_t *expr = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after expression");
|
||||
return expr;
|
||||
@ -99,10 +76,9 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
|
||||
node->data.new_expr.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
|
||||
node->data.new_expr.arguments_count = 0;
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACKET)) {
|
||||
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
|
||||
_rava_parser_parse_expression(parser);
|
||||
}
|
||||
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
|
||||
_rava_parser_parse_expression(parser);
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RBRACKET, "Expected ']' after array size");
|
||||
|
||||
while (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
|
||||
@ -328,51 +304,13 @@ static RavaASTNode_t* _rava_parser_parse_additive(RavaParser_t *parser) {
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_shift(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_additive(parser);
|
||||
|
||||
while (_rava_parser_check(parser, RAVA_TOKEN_LSHIFT) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_RSHIFT) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_URSHIFT)) {
|
||||
|
||||
RavaBinaryOp_e op;
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_LSHIFT)) op = RAVA_BINOP_LSHIFT;
|
||||
else if (_rava_parser_match(parser, RAVA_TOKEN_RSHIFT)) op = RAVA_BINOP_RSHIFT;
|
||||
else { _rava_parser_advance(parser); op = RAVA_BINOP_URSHIFT; }
|
||||
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.binary.op = op;
|
||||
node->data.binary.left = left;
|
||||
node->data.binary.right = _rava_parser_parse_additive(parser);
|
||||
left = node;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_relational(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_shift(parser);
|
||||
RavaASTNode_t *left = _rava_parser_parse_additive(parser);
|
||||
|
||||
while (_rava_parser_check(parser, RAVA_TOKEN_LT) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_GT) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_LE) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_GE) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INSTANCEOF)) {
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_INSTANCEOF)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_INSTANCEOF_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.instanceof_expr.expression = left;
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
node->data.instanceof_expr.type_name = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
left = node;
|
||||
continue;
|
||||
}
|
||||
_rava_parser_check(parser, RAVA_TOKEN_GE)) {
|
||||
|
||||
RavaBinaryOp_e op;
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_LT)) op = RAVA_BINOP_LT;
|
||||
@ -414,56 +352,8 @@ static RavaASTNode_t* _rava_parser_parse_equality(RavaParser_t *parser) {
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_bitwise_and(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_equality(parser);
|
||||
|
||||
while (_rava_parser_match(parser, RAVA_TOKEN_AMP)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.binary.op = RAVA_BINOP_BITAND;
|
||||
node->data.binary.left = left;
|
||||
node->data.binary.right = _rava_parser_parse_equality(parser);
|
||||
left = node;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_bitwise_xor(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_bitwise_and(parser);
|
||||
|
||||
while (_rava_parser_match(parser, RAVA_TOKEN_CARET)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.binary.op = RAVA_BINOP_BITXOR;
|
||||
node->data.binary.left = left;
|
||||
node->data.binary.right = _rava_parser_parse_bitwise_and(parser);
|
||||
left = node;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_bitwise_or(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_bitwise_xor(parser);
|
||||
|
||||
while (_rava_parser_match(parser, RAVA_TOKEN_PIPE)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.binary.op = RAVA_BINOP_BITOR;
|
||||
node->data.binary.left = left;
|
||||
node->data.binary.right = _rava_parser_parse_bitwise_xor(parser);
|
||||
left = node;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_logical_and(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_bitwise_or(parser);
|
||||
RavaASTNode_t *left = _rava_parser_parse_equality(parser);
|
||||
|
||||
while (_rava_parser_match(parser, RAVA_TOKEN_AND)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
||||
@ -471,7 +361,7 @@ static RavaASTNode_t* _rava_parser_parse_logical_and(RavaParser_t *parser) {
|
||||
parser->current_token->column);
|
||||
node->data.binary.op = RAVA_BINOP_AND;
|
||||
node->data.binary.left = left;
|
||||
node->data.binary.right = _rava_parser_parse_bitwise_or(parser);
|
||||
node->data.binary.right = _rava_parser_parse_equality(parser);
|
||||
left = node;
|
||||
}
|
||||
|
||||
@ -494,25 +384,8 @@ static RavaASTNode_t* _rava_parser_parse_logical_or(RavaParser_t *parser) {
|
||||
return left;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_ternary(RavaParser_t *parser) {
|
||||
RavaASTNode_t *condition = _rava_parser_parse_logical_or(parser);
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_QUESTION)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_TERNARY_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.ternary.condition = condition;
|
||||
node->data.ternary.true_expr = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_COLON, "Expected ':' in ternary expression");
|
||||
node->data.ternary.false_expr = _rava_parser_parse_ternary(parser);
|
||||
return node;
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
static RavaASTNode_t* _rava_parser_parse_assignment(RavaParser_t *parser) {
|
||||
RavaASTNode_t *left = _rava_parser_parse_ternary(parser);
|
||||
RavaASTNode_t *left = _rava_parser_parse_logical_or(parser);
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ASSIGN_EXPR,
|
||||
@ -555,34 +428,6 @@ static RavaASTNode_t* _rava_parser_parse_assignment(RavaParser_t *parser) {
|
||||
return left;
|
||||
}
|
||||
|
||||
RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ARRAY_INIT_EXPR,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' for array initializer");
|
||||
|
||||
size_t capacity = 8;
|
||||
node->data.array_init.elements = malloc(sizeof(RavaASTNode_t*) * capacity);
|
||||
node->data.array_init.elements_count = 0;
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE)) {
|
||||
do {
|
||||
if (node->data.array_init.elements_count >= capacity) {
|
||||
capacity *= 2;
|
||||
node->data.array_init.elements = realloc(node->data.array_init.elements,
|
||||
sizeof(RavaASTNode_t*) * capacity);
|
||||
}
|
||||
node->data.array_init.elements[node->data.array_init.elements_count++] =
|
||||
_rava_parser_parse_expression(parser);
|
||||
} while (_rava_parser_match(parser, RAVA_TOKEN_COMMA));
|
||||
}
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' after array initializer");
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser) {
|
||||
return _rava_parser_parse_assignment(parser);
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ extern bool _rava_parser_check(RavaParser_t *parser, RavaTokenType_e type);
|
||||
extern bool _rava_parser_match(RavaParser_t *parser, RavaTokenType_e type);
|
||||
extern bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char *message);
|
||||
extern RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
|
||||
extern RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser);
|
||||
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
|
||||
|
||||
RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser);
|
||||
@ -73,26 +72,11 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_DO)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_DO_WHILE_STMT,
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FOR)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
|
||||
node->data.while_stmt.body = _rava_parser_parse_statement(parser);
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_KEYWORD_WHILE, "Expected 'while' after do body");
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'while'");
|
||||
node->data.while_stmt.condition = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after do-while condition");
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after do-while");
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FOR)) {
|
||||
int line = parser->current_token->line;
|
||||
int column = parser->current_token->column;
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'for'");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
||||
@ -110,154 +94,41 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
|
||||
}
|
||||
if (is_type_decl) {
|
||||
RavaASTNode_t *type = _rava_parser_parse_type(parser);
|
||||
char *var_name = NULL;
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
var_name = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_COLON)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ENHANCED_FOR_STMT, line, column);
|
||||
node->data.enhanced_for.var_type = type;
|
||||
node->data.enhanced_for.var_name = var_name;
|
||||
node->data.enhanced_for.iterable = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after enhanced for");
|
||||
node->data.enhanced_for.body = _rava_parser_parse_statement(parser);
|
||||
return node;
|
||||
}
|
||||
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
||||
RavaASTNode_t *var_decl = rava_ast_node_create(RAVA_AST_VAR_DECL,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
var_decl->data.var_decl.type = type;
|
||||
var_decl->data.var_decl.name = var_name;
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
var_decl->data.var_decl.name = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
||||
}
|
||||
node->data.for_stmt.init = var_decl;
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
||||
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.condition = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
||||
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.update = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
||||
|
||||
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
||||
return node;
|
||||
} else {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
||||
node->data.for_stmt.init = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
||||
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.condition = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
||||
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.update = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
||||
|
||||
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
||||
return node;
|
||||
}
|
||||
} else {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
||||
node->data.for_stmt.init = NULL;
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
||||
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.condition = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
||||
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
||||
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.update = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
||||
|
||||
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_SWITCH)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_SWITCH_STMT,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'switch'");
|
||||
node->data.switch_stmt.expression = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after switch expression");
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after switch");
|
||||
|
||||
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_CASE)) {
|
||||
RavaASTNode_t *case_node = rava_ast_node_create(RAVA_AST_CASE_STMT,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
case_node->data.case_stmt.is_default = false;
|
||||
case_node->data.case_stmt.value = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_COLON, "Expected ':' after case value");
|
||||
|
||||
while (!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CASE) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DEFAULT) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
||||
RavaASTNode_t *stmt = _rava_parser_parse_statement(parser);
|
||||
if (stmt) {
|
||||
rava_ast_node_add_child(case_node, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
rava_ast_node_add_child(node, case_node);
|
||||
|
||||
} else if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_DEFAULT)) {
|
||||
RavaASTNode_t *default_node = rava_ast_node_create(RAVA_AST_CASE_STMT,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
default_node->data.case_stmt.is_default = true;
|
||||
default_node->data.case_stmt.value = NULL;
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_COLON, "Expected ':' after default");
|
||||
|
||||
while (!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CASE) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DEFAULT) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
||||
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
||||
RavaASTNode_t *stmt = _rava_parser_parse_statement(parser);
|
||||
if (stmt) {
|
||||
rava_ast_node_add_child(default_node, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
rava_ast_node_add_child(node, default_node);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
||||
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.condition = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' at end of switch");
|
||||
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
||||
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
node->data.for_stmt.update = NULL;
|
||||
}
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
||||
|
||||
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -294,65 +165,6 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_THROW)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_THROW_STMT,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
node->data.throw_stmt.expression = _rava_parser_parse_expression(parser);
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after throw");
|
||||
return node;
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_TRY)) {
|
||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_TRY_STMT,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
|
||||
node->data.try_stmt.try_block = _rava_parser_parse_block(parser);
|
||||
node->data.try_stmt.catch_clauses = NULL;
|
||||
node->data.try_stmt.catch_count = 0;
|
||||
node->data.try_stmt.finally_block = NULL;
|
||||
|
||||
size_t capacity = 4;
|
||||
node->data.try_stmt.catch_clauses = malloc(capacity * sizeof(RavaASTNode_t*));
|
||||
|
||||
while (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_CATCH)) {
|
||||
RavaASTNode_t *catch_node = rava_ast_node_create(RAVA_AST_CATCH_CLAUSE,
|
||||
parser->current_token->line,
|
||||
parser->current_token->column);
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after catch");
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
catch_node->data.catch_clause.exception_type = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||
catch_node->data.catch_clause.exception_name = strdup(parser->current_token->lexeme);
|
||||
_rava_parser_advance(parser);
|
||||
}
|
||||
|
||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after catch parameter");
|
||||
|
||||
catch_node->data.catch_clause.body = _rava_parser_parse_block(parser);
|
||||
|
||||
if (node->data.try_stmt.catch_count >= capacity) {
|
||||
capacity *= 2;
|
||||
node->data.try_stmt.catch_clauses = realloc(
|
||||
node->data.try_stmt.catch_clauses,
|
||||
capacity * sizeof(RavaASTNode_t*));
|
||||
}
|
||||
node->data.try_stmt.catch_clauses[node->data.try_stmt.catch_count++] = catch_node;
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FINALLY)) {
|
||||
node->data.try_stmt.finally_block = _rava_parser_parse_block(parser);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
bool is_type_decl = false;
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
|
||||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) ||
|
||||
@ -382,11 +194,7 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
|
||||
}
|
||||
|
||||
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
|
||||
var_decl->data.var_decl.initializer = _rava_parser_parse_array_initializer(parser);
|
||||
} else {
|
||||
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
||||
}
|
||||
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
||||
} else {
|
||||
var_decl->data.var_decl.initializer = NULL;
|
||||
}
|
||||
|
||||
1179
runtime/runtime.c
1179
runtime/runtime.c
File diff suppressed because it is too large
Load Diff
@ -88,20 +88,6 @@ typedef struct {
|
||||
|
||||
struct MethodCache_s;
|
||||
|
||||
typedef struct {
|
||||
int catch_label;
|
||||
int finally_label;
|
||||
int end_label;
|
||||
int exception_local;
|
||||
size_t stack_depth;
|
||||
} RavaExceptionHandler_t;
|
||||
|
||||
typedef struct {
|
||||
RavaExceptionHandler_t *handlers;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} RavaExceptionStack_t;
|
||||
|
||||
typedef struct {
|
||||
RavaProgram_t *program;
|
||||
RavaCallStack_t *call_stack;
|
||||
@ -109,9 +95,6 @@ typedef struct {
|
||||
struct MethodCache_s *method_cache;
|
||||
char *error_message;
|
||||
bool had_error;
|
||||
bool has_exception;
|
||||
RavaValue_t exception_value;
|
||||
RavaExceptionStack_t *exception_stack;
|
||||
} RavaVM_t;
|
||||
|
||||
RavaValue_t rava_value_int(int32_t value);
|
||||
|
||||
@ -125,13 +125,11 @@ static bool _rava_semantic_analyze_method(RavaSemanticAnalyzer_t *analyzer, Rava
|
||||
static bool _rava_semantic_analyze_field(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *field_node) {
|
||||
if (field_node->type != RAVA_AST_FIELD_DECL) return false;
|
||||
|
||||
char *field_name = field_node->data.field_decl.name;
|
||||
RavaType_t *field_type = _rava_semantic_resolve_type(analyzer, field_node->data.field_decl.type);
|
||||
char *field_name = field_node->data.var_decl.name;
|
||||
RavaType_t *field_type = _rava_semantic_resolve_type(analyzer, field_node->data.var_decl.type);
|
||||
|
||||
RavaSymbol_t *field_symbol = rava_symbol_create(RAVA_SYMBOL_FIELD, field_name, field_type);
|
||||
field_symbol->declaration = field_node;
|
||||
field_symbol->modifiers = field_node->data.field_decl.modifiers;
|
||||
field_symbol->modifiers_count = field_node->data.field_decl.modifiers_count;
|
||||
|
||||
if (!rava_symbol_table_define(analyzer->symbol_table, field_symbol)) {
|
||||
char error_msg[256];
|
||||
@ -141,8 +139,8 @@ static bool _rava_semantic_analyze_field(RavaSemanticAnalyzer_t *analyzer, RavaA
|
||||
return false;
|
||||
}
|
||||
|
||||
if (field_node->data.field_decl.initializer) {
|
||||
RavaType_t *init_type = _rava_semantic_check_expression(analyzer, field_node->data.field_decl.initializer);
|
||||
if (field_node->data.var_decl.initializer) {
|
||||
RavaType_t *init_type = _rava_semantic_check_expression(analyzer, field_node->data.var_decl.initializer);
|
||||
if (init_type && !rava_type_is_assignable_to(init_type, field_type)) {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg),
|
||||
@ -301,20 +299,6 @@ static RavaType_t* _rava_semantic_check_expression(RavaSemanticAnalyzer_t *analy
|
||||
return rava_type_create_primitive(RAVA_TYPE_LONG);
|
||||
}
|
||||
}
|
||||
if (member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR &&
|
||||
strcmp(member->data.member_access.object->data.identifier.name, "Math") == 0) {
|
||||
if (strcmp(method, "abs") == 0 || strcmp(method, "min") == 0 || strcmp(method, "max") == 0) {
|
||||
return rava_type_create_primitive(RAVA_TYPE_INT);
|
||||
} else if (strcmp(method, "round") == 0) {
|
||||
return rava_type_create_primitive(RAVA_TYPE_LONG);
|
||||
} else if (strcmp(method, "sqrt") == 0 || strcmp(method, "pow") == 0 ||
|
||||
strcmp(method, "floor") == 0 || strcmp(method, "ceil") == 0 ||
|
||||
strcmp(method, "sin") == 0 || strcmp(method, "cos") == 0 ||
|
||||
strcmp(method, "tan") == 0 || strcmp(method, "log") == 0 ||
|
||||
strcmp(method, "exp") == 0 || strcmp(method, "random") == 0) {
|
||||
return rava_type_create_primitive(RAVA_TYPE_DOUBLE);
|
||||
}
|
||||
}
|
||||
if (strcmp(method, "length") == 0) {
|
||||
return rava_type_create_primitive(RAVA_TYPE_INT);
|
||||
} else if (strcmp(method, "charAt") == 0) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user