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
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra -Werror -std=gnu99 -O3 -march=native -I.
|
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_SOURCES = lexer/lexer_tokenizer.c lexer/lexer_keywords.c lexer/lexer_literals.c
|
||||||
LEXER_OBJECTS = $(LEXER_SOURCES:.c=.o)
|
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_SOURCES = tests/test_fileio.c
|
||||||
TEST_FILEIO_OBJECTS = $(TEST_FILEIO_SOURCES:.c=.o)
|
TEST_FILEIO_OBJECTS = $(TEST_FILEIO_SOURCES:.c=.o)
|
||||||
|
|
||||||
TEST_DOWHILE_SOURCES = tests/test_dowhile.c
|
all: test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio
|
||||||
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
|
|
||||||
|
|
||||||
test_lexer: $(LEXER_OBJECTS) $(TEST_LEXER_OBJECTS)
|
test_lexer: $(LEXER_OBJECTS) $(TEST_LEXER_OBJECTS)
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(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)
|
test_fileio: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_FILEIO_OBJECTS)
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(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
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
@ -222,17 +150,8 @@ clean:
|
|||||||
$(PHASE0_OBJECTS) \
|
$(PHASE0_OBJECTS) \
|
||||||
$(TEST_LEXER_OBJECTS) $(TEST_PARSER_OBJECTS) $(TEST_SEMANTIC_OBJECTS) $(TEST_IR_OBJECTS) $(TEST_RUNTIME_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_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_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_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
|
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
|
.PHONY: all clean benchmark test_phase0 pgo test_benchmark_pgo_gen pgo_run test_benchmark_pgo
|
||||||
|
|
||||||
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 ==="
|
|
||||||
|
|||||||
15
README.md
15
README.md
@ -17,13 +17,10 @@ The pipeline:
|
|||||||
|
|
||||||
Supported features:
|
Supported features:
|
||||||
- Primitives: int, long, double, boolean, char
|
- Primitives: int, long, double, boolean, char
|
||||||
- Arrays, strings, and array initializers
|
- Arrays and strings
|
||||||
- Objects, instance methods, and instanceof
|
- Objects and instance methods
|
||||||
- Inheritance and interfaces
|
- Inheritance
|
||||||
- Control flow: if/else, while, do-while, for, enhanced for-each, switch/case, break, continue
|
- Control flow: if/else, while, for, break, continue
|
||||||
- Operators: arithmetic, bitwise (AND, OR, XOR, shifts), ternary (? :)
|
|
||||||
- Exception handling: try/catch/finally, throw
|
|
||||||
- Math functions and String methods
|
|
||||||
- File I/O
|
- File I/O
|
||||||
- Recursion
|
- Recursion
|
||||||
- System.out.println
|
- System.out.println
|
||||||
@ -62,10 +59,10 @@ Run the benchmark:
|
|||||||
make benchmark
|
make benchmark
|
||||||
```
|
```
|
||||||
|
|
||||||
Run all tests:
|
Run tests:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make test
|
make test_runtime && ./test_runtime
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance
|
## 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,
|
||||||
RAVA_OP_CALL_STATIC,
|
RAVA_OP_CALL_STATIC,
|
||||||
RAVA_OP_CALL_VIRTUAL,
|
RAVA_OP_CALL_VIRTUAL,
|
||||||
RAVA_OP_CALL_SUPER,
|
|
||||||
RAVA_OP_CALL_NATIVE,
|
RAVA_OP_CALL_NATIVE,
|
||||||
RAVA_OP_RETURN,
|
RAVA_OP_RETURN,
|
||||||
RAVA_OP_RETURN_VOID,
|
RAVA_OP_RETURN_VOID,
|
||||||
@ -68,8 +67,6 @@ typedef enum {
|
|||||||
RAVA_OP_INSTANCEOF,
|
RAVA_OP_INSTANCEOF,
|
||||||
|
|
||||||
RAVA_OP_THROW,
|
RAVA_OP_THROW,
|
||||||
RAVA_OP_TRY_BEGIN,
|
|
||||||
RAVA_OP_TRY_END,
|
|
||||||
RAVA_OP_POP,
|
RAVA_OP_POP,
|
||||||
RAVA_OP_DUP,
|
RAVA_OP_DUP,
|
||||||
|
|
||||||
@ -81,13 +78,6 @@ typedef enum {
|
|||||||
RAVA_OP_STRING_SUBSTRING,
|
RAVA_OP_STRING_SUBSTRING,
|
||||||
RAVA_OP_STRING_EQUALS,
|
RAVA_OP_STRING_EQUALS,
|
||||||
RAVA_OP_STRING_COMPARETO,
|
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,
|
RAVA_OP_LOAD_THIS,
|
||||||
|
|
||||||
@ -106,22 +96,7 @@ typedef enum {
|
|||||||
RAVA_OP_LOAD_LOCAL_CONST_LE_JUMPFALSE,
|
RAVA_OP_LOAD_LOCAL_CONST_LE_JUMPFALSE,
|
||||||
RAVA_OP_LOAD_TWO_LOCALS,
|
RAVA_OP_LOAD_TWO_LOCALS,
|
||||||
RAVA_OP_ADD_LOCAL_TO_LOCAL,
|
RAVA_OP_ADD_LOCAL_TO_LOCAL,
|
||||||
RAVA_OP_LOAD_LOCAL_LT_LOCAL_JUMPFALSE,
|
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
|
|
||||||
} RavaOpCode_e;
|
} RavaOpCode_e;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@ -160,12 +135,6 @@ typedef union {
|
|||||||
int local2;
|
int local2;
|
||||||
int label_id;
|
int label_id;
|
||||||
} cmp_locals;
|
} cmp_locals;
|
||||||
struct {
|
|
||||||
int catch_label;
|
|
||||||
int finally_label;
|
|
||||||
int end_label;
|
|
||||||
int exception_local;
|
|
||||||
} try_handler;
|
|
||||||
} RavaOperand_u;
|
} RavaOperand_u;
|
||||||
|
|
||||||
typedef struct {
|
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;
|
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* rava_ir_generator_create(RavaSemanticAnalyzer_t *analyzer) {
|
||||||
RavaIRGenerator_t *gen = calloc(1, sizeof(RavaIRGenerator_t));
|
RavaIRGenerator_t *gen = calloc(1, sizeof(RavaIRGenerator_t));
|
||||||
gen->program = rava_program_create();
|
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_GE: instr.opcode = RAVA_OP_GE; break;
|
||||||
case RAVA_BINOP_AND: instr.opcode = RAVA_OP_AND; break;
|
case RAVA_BINOP_AND: instr.opcode = RAVA_OP_AND; break;
|
||||||
case RAVA_BINOP_OR: instr.opcode = RAVA_OP_OR; 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;
|
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;
|
instr.opcode = RAVA_OP_STORE_ARRAY;
|
||||||
_rava_ir_emit(gen, instr);
|
_rava_ir_emit(gen, instr);
|
||||||
} else if (expr->data.assign.target->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
} 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.target->data.member_access.object);
|
||||||
_rava_ir_gen_expression(gen, expr->data.assign.value);
|
_rava_ir_gen_expression(gen, expr->data.assign.value);
|
||||||
instr.opcode = RAVA_OP_PUT_FIELD;
|
instr.opcode = RAVA_OP_PUT_FIELD;
|
||||||
@ -238,17 +210,6 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RAVA_AST_MEMBER_ACCESS_EXPR:
|
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);
|
_rava_ir_gen_expression(gen, expr->data.member_access.object);
|
||||||
instr.opcode = RAVA_OP_GET_FIELD;
|
instr.opcode = RAVA_OP_GET_FIELD;
|
||||||
instr.operand.field.field_name = strdup(expr->data.member_access.member);
|
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_print = false;
|
||||||
bool is_string_length = false;
|
bool is_string_length = false;
|
||||||
bool is_string_charat = false;
|
bool is_string_charat = false;
|
||||||
bool is_string_substring = false;
|
|
||||||
bool is_string_equals = 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_read = false;
|
||||||
bool is_file_write = false;
|
bool is_file_write = false;
|
||||||
bool is_file_exists = false;
|
bool is_file_exists = false;
|
||||||
bool is_file_delete = false;
|
bool is_file_delete = false;
|
||||||
bool is_current_time_millis = false;
|
bool is_current_time_millis = false;
|
||||||
bool is_nano_time = 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;
|
RavaASTNode_t *string_object = NULL;
|
||||||
|
|
||||||
if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
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;
|
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) {
|
if (strcmp(member->data.member_access.member, "length") == 0 && expr->data.call.arguments_count == 0) {
|
||||||
is_string_length = true;
|
is_string_length = true;
|
||||||
string_object = member->data.member_access.object;
|
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) {
|
} else if (strcmp(member->data.member_access.member, "equals") == 0 && expr->data.call.arguments_count == 1) {
|
||||||
is_string_equals = true;
|
is_string_equals = true;
|
||||||
string_object = member->data.member_access.object;
|
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]);
|
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||||
instr.opcode = RAVA_OP_STRING_EQUALS;
|
instr.opcode = RAVA_OP_STRING_EQUALS;
|
||||||
_rava_ir_emit(gen, instr);
|
_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) {
|
} else if (is_println || is_print) {
|
||||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[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);
|
_rava_ir_emit(gen, instr);
|
||||||
} else if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
} else if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||||
RavaASTNode_t *member = expr->data.call.callee;
|
RavaASTNode_t *member = expr->data.call.callee;
|
||||||
if (member->data.member_access.object->type == RAVA_AST_SUPER_EXPR) {
|
_rava_ir_gen_expression(gen, member->data.member_access.object);
|
||||||
instr.opcode = RAVA_OP_LOAD_THIS;
|
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||||
_rava_ir_emit(gen, instr);
|
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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 {
|
} else {
|
||||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[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);
|
_rava_ir_emit(gen, instr);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -767,33 +463,6 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
|||||||
break;
|
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: {
|
case RAVA_AST_FOR_STMT: {
|
||||||
if (stmt->data.for_stmt.init) {
|
if (stmt->data.for_stmt.init) {
|
||||||
if (stmt->data.for_stmt.init->type == RAVA_AST_VAR_DECL) {
|
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;
|
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:
|
case RAVA_AST_RETURN_STMT:
|
||||||
if (stmt->data.return_stmt.value) {
|
if (stmt->data.return_stmt.value) {
|
||||||
_rava_ir_gen_expression(gen, 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;
|
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:
|
case RAVA_AST_BREAK_STMT:
|
||||||
if (gen->loop_context) {
|
if (gen->loop_context) {
|
||||||
instr.opcode = RAVA_OP_JUMP;
|
instr.opcode = RAVA_OP_JUMP;
|
||||||
@ -1041,76 +562,6 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,19 +157,11 @@ struct RavaASTNode_t {
|
|||||||
struct {
|
struct {
|
||||||
char *name;
|
char *name;
|
||||||
char *superclass;
|
char *superclass;
|
||||||
char **interfaces;
|
|
||||||
size_t interfaces_count;
|
|
||||||
RavaASTNode_t *type;
|
RavaASTNode_t *type;
|
||||||
RavaModifier_e *modifiers;
|
RavaModifier_e *modifiers;
|
||||||
size_t modifiers_count;
|
size_t modifiers_count;
|
||||||
} class_decl;
|
} class_decl;
|
||||||
|
|
||||||
struct {
|
|
||||||
char *name;
|
|
||||||
RavaModifier_e *modifiers;
|
|
||||||
size_t modifiers_count;
|
|
||||||
} interface_decl;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char *name;
|
char *name;
|
||||||
RavaASTNode_t *return_type;
|
RavaASTNode_t *return_type;
|
||||||
@ -183,14 +175,6 @@ struct RavaASTNode_t {
|
|||||||
RavaASTNode_t *initializer;
|
RavaASTNode_t *initializer;
|
||||||
} var_decl;
|
} var_decl;
|
||||||
|
|
||||||
struct {
|
|
||||||
char *name;
|
|
||||||
RavaASTNode_t *type;
|
|
||||||
RavaASTNode_t *initializer;
|
|
||||||
RavaModifier_e *modifiers;
|
|
||||||
size_t modifiers_count;
|
|
||||||
} field_decl;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
RavaASTNode_t *condition;
|
RavaASTNode_t *condition;
|
||||||
RavaASTNode_t *then_stmt;
|
RavaASTNode_t *then_stmt;
|
||||||
@ -209,13 +193,6 @@ struct RavaASTNode_t {
|
|||||||
RavaASTNode_t *body;
|
RavaASTNode_t *body;
|
||||||
} for_stmt;
|
} for_stmt;
|
||||||
|
|
||||||
struct {
|
|
||||||
RavaASTNode_t *var_type;
|
|
||||||
char *var_name;
|
|
||||||
RavaASTNode_t *iterable;
|
|
||||||
RavaASTNode_t *body;
|
|
||||||
} enhanced_for;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
RavaASTNode_t *value;
|
RavaASTNode_t *value;
|
||||||
} return_stmt;
|
} return_stmt;
|
||||||
@ -252,42 +229,6 @@ struct RavaASTNode_t {
|
|||||||
RavaASTNode_t *type;
|
RavaASTNode_t *type;
|
||||||
RavaASTNode_t *expression;
|
RavaASTNode_t *expression;
|
||||||
} cast;
|
} 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;
|
} 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 = modifiers;
|
||||||
class_decl->data.class_decl.modifiers_count = modifiers_count;
|
class_decl->data.class_decl.modifiers_count = modifiers_count;
|
||||||
class_decl->data.class_decl.superclass = NULL;
|
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)) {
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
||||||
class_decl->data.class_decl.name = strdup(parser->current_token->lexeme);
|
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");
|
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after class name");
|
||||||
|
|
||||||
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
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,
|
RavaASTNode_t *field = rava_ast_node_create(RAVA_AST_FIELD_DECL,
|
||||||
parser->current_token->line,
|
parser->current_token->line,
|
||||||
parser->current_token->column);
|
parser->current_token->column);
|
||||||
field->data.field_decl.type = member_type;
|
field->data.var_decl.type = member_type;
|
||||||
field->data.field_decl.name = name;
|
field->data.var_decl.name = name;
|
||||||
field->data.field_decl.modifiers = member_modifiers;
|
|
||||||
field->data.field_decl.modifiers_count = member_modifiers_count;
|
|
||||||
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
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 {
|
} 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_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after field declaration");
|
||||||
rava_ast_node_add_child(class_decl, field);
|
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;
|
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* rava_parser_parse(RavaParser_t *parser) {
|
||||||
RavaASTNode_t *root = rava_ast_node_create(RAVA_AST_COMPILATION_UNIT, 1, 1);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
RavaModifier_e *modifiers = NULL;
|
RavaASTNode_t *decl = _rava_parser_parse_class_declaration(parser);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decl) {
|
if (decl) {
|
||||||
rava_ast_node_add_child(root, 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);
|
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
|
||||||
|
|
||||||
RavaASTNode_t* _rava_parser_parse_expression(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) {
|
static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
|
||||||
RavaASTNode_t *node = NULL;
|
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 (_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);
|
RavaASTNode_t *expr = _rava_parser_parse_expression(parser);
|
||||||
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after expression");
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after expression");
|
||||||
return expr;
|
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 = malloc(sizeof(RavaASTNode_t*) * args_capacity);
|
||||||
node->data.new_expr.arguments_count = 0;
|
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++] =
|
||||||
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
|
_rava_parser_parse_expression(parser);
|
||||||
_rava_parser_parse_expression(parser);
|
|
||||||
}
|
|
||||||
_rava_parser_expect(parser, RAVA_TOKEN_RBRACKET, "Expected ']' after array size");
|
_rava_parser_expect(parser, RAVA_TOKEN_RBRACKET, "Expected ']' after array size");
|
||||||
|
|
||||||
while (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
|
while (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
|
||||||
@ -328,51 +304,13 @@ static RavaASTNode_t* _rava_parser_parse_additive(RavaParser_t *parser) {
|
|||||||
return left;
|
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) {
|
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) ||
|
while (_rava_parser_check(parser, RAVA_TOKEN_LT) ||
|
||||||
_rava_parser_check(parser, RAVA_TOKEN_GT) ||
|
_rava_parser_check(parser, RAVA_TOKEN_GT) ||
|
||||||
_rava_parser_check(parser, RAVA_TOKEN_LE) ||
|
_rava_parser_check(parser, RAVA_TOKEN_LE) ||
|
||||||
_rava_parser_check(parser, RAVA_TOKEN_GE) ||
|
_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
RavaBinaryOp_e op;
|
RavaBinaryOp_e op;
|
||||||
if (_rava_parser_match(parser, RAVA_TOKEN_LT)) op = RAVA_BINOP_LT;
|
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;
|
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) {
|
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)) {
|
while (_rava_parser_match(parser, RAVA_TOKEN_AND)) {
|
||||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
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);
|
parser->current_token->column);
|
||||||
node->data.binary.op = RAVA_BINOP_AND;
|
node->data.binary.op = RAVA_BINOP_AND;
|
||||||
node->data.binary.left = left;
|
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;
|
left = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,25 +384,8 @@ static RavaASTNode_t* _rava_parser_parse_logical_or(RavaParser_t *parser) {
|
|||||||
return left;
|
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) {
|
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)) {
|
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ASSIGN_EXPR,
|
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;
|
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) {
|
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser) {
|
||||||
return _rava_parser_parse_assignment(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_match(RavaParser_t *parser, RavaTokenType_e type);
|
||||||
extern bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char *message);
|
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_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);
|
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
|
||||||
|
|
||||||
RavaASTNode_t* _rava_parser_parse_statement(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;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_DO)) {
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FOR)) {
|
||||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_DO_WHILE_STMT,
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT,
|
||||||
parser->current_token->line,
|
parser->current_token->line,
|
||||||
parser->current_token->column);
|
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'");
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'for'");
|
||||||
|
|
||||||
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
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) {
|
if (is_type_decl) {
|
||||||
RavaASTNode_t *type = _rava_parser_parse_type(parser);
|
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,
|
RavaASTNode_t *var_decl = rava_ast_node_create(RAVA_AST_VAR_DECL,
|
||||||
parser->current_token->line,
|
parser->current_token->line,
|
||||||
parser->current_token->column);
|
parser->current_token->column);
|
||||||
var_decl->data.var_decl.type = type;
|
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)) {
|
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||||
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
||||||
}
|
}
|
||||||
node->data.for_stmt.init = var_decl;
|
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 {
|
} else {
|
||||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
|
||||||
node->data.for_stmt.init = _rava_parser_parse_expression(parser);
|
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 {
|
} else {
|
||||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
|
||||||
node->data.for_stmt.init = NULL;
|
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)) {
|
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
||||||
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_SWITCH_STMT,
|
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
||||||
parser->current_token->line,
|
} else {
|
||||||
parser->current_token->column);
|
node->data.for_stmt.condition = NULL;
|
||||||
|
|
||||||
_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_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;
|
return node;
|
||||||
}
|
}
|
||||||
@ -294,65 +165,6 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
|
|||||||
return node;
|
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;
|
bool is_type_decl = false;
|
||||||
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
|
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
|
||||||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) ||
|
_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_match(parser, RAVA_TOKEN_ASSIGN)) {
|
||||||
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
|
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
||||||
var_decl->data.var_decl.initializer = _rava_parser_parse_array_initializer(parser);
|
|
||||||
} else {
|
|
||||||
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var_decl->data.var_decl.initializer = NULL;
|
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;
|
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 {
|
typedef struct {
|
||||||
RavaProgram_t *program;
|
RavaProgram_t *program;
|
||||||
RavaCallStack_t *call_stack;
|
RavaCallStack_t *call_stack;
|
||||||
@ -109,9 +95,6 @@ typedef struct {
|
|||||||
struct MethodCache_s *method_cache;
|
struct MethodCache_s *method_cache;
|
||||||
char *error_message;
|
char *error_message;
|
||||||
bool had_error;
|
bool had_error;
|
||||||
bool has_exception;
|
|
||||||
RavaValue_t exception_value;
|
|
||||||
RavaExceptionStack_t *exception_stack;
|
|
||||||
} RavaVM_t;
|
} RavaVM_t;
|
||||||
|
|
||||||
RavaValue_t rava_value_int(int32_t value);
|
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) {
|
static bool _rava_semantic_analyze_field(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *field_node) {
|
||||||
if (field_node->type != RAVA_AST_FIELD_DECL) return false;
|
if (field_node->type != RAVA_AST_FIELD_DECL) return false;
|
||||||
|
|
||||||
char *field_name = field_node->data.field_decl.name;
|
char *field_name = field_node->data.var_decl.name;
|
||||||
RavaType_t *field_type = _rava_semantic_resolve_type(analyzer, field_node->data.field_decl.type);
|
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);
|
RavaSymbol_t *field_symbol = rava_symbol_create(RAVA_SYMBOL_FIELD, field_name, field_type);
|
||||||
field_symbol->declaration = field_node;
|
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)) {
|
if (!rava_symbol_table_define(analyzer->symbol_table, field_symbol)) {
|
||||||
char error_msg[256];
|
char error_msg[256];
|
||||||
@ -141,8 +139,8 @@ static bool _rava_semantic_analyze_field(RavaSemanticAnalyzer_t *analyzer, RavaA
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (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.field_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)) {
|
if (init_type && !rava_type_is_assignable_to(init_type, field_type)) {
|
||||||
char error_msg[256];
|
char error_msg[256];
|
||||||
snprintf(error_msg, sizeof(error_msg),
|
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);
|
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) {
|
if (strcmp(method, "length") == 0) {
|
||||||
return rava_type_create_primitive(RAVA_TYPE_INT);
|
return rava_type_create_primitive(RAVA_TYPE_INT);
|
||||||
} else if (strcmp(method, "charAt") == 0) {
|
} else if (strcmp(method, "charAt") == 0) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user