diff --git a/Makefile b/Makefile index 613296c..11bf603 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,13 @@ TEST_INSTANCEOF_OBJECTS = $(TEST_INSTANCEOF_SOURCES:.c=.o) TEST_SHORTCIRCUIT_SOURCES = tests/test_shortcircuit.c TEST_SHORTCIRCUIT_OBJECTS = $(TEST_SHORTCIRCUIT_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_shortcircuit +TEST_MULTIDIM_ARRAYS_SOURCES = tests/test_multidim_arrays.c +TEST_MULTIDIM_ARRAYS_OBJECTS = $(TEST_MULTIDIM_ARRAYS_SOURCES:.c=.o) + +TEST_STATIC_INIT_SOURCES = tests/test_static_init.c +TEST_STATIC_INIT_OBJECTS = $(TEST_STATIC_INIT_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_shortcircuit test_multidim_arrays test_static_init test_lexer: $(LEXER_OBJECTS) $(TEST_LEXER_OBJECTS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) @@ -163,6 +169,12 @@ test_instanceof: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_ test_shortcircuit: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_SHORTCIRCUIT_OBJECTS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) +test_multidim_arrays: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_MULTIDIM_ARRAYS_OBJECTS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +test_static_init: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_STATIC_INIT_OBJECTS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ @@ -228,8 +240,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_SHORTCIRCUIT_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_shortcircuit test_benchmark \ + $(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_SHORTCIRCUIT_OBJECTS) $(TEST_MULTIDIM_ARRAYS_OBJECTS) $(TEST_STATIC_INIT_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_shortcircuit test_multidim_arrays test_static_init 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 @@ -241,5 +253,5 @@ test: all ./test_fileio && ./test_dowhile && ./test_switch && ./test_math && ./test_string_methods && \ ./test_static && ./test_interfaces && ./test_exceptions && ./test_ternary && \ ./test_bitwise && ./test_enhanced_for && ./test_array_init && ./test_instanceof && \ - ./test_shortcircuit && \ + ./test_shortcircuit && ./test_multidim_arrays && ./test_static_init && \ echo "" && echo "=== All Tests Passed ===" diff --git a/ir/ir.c b/ir/ir.c index da1d92e..c177b95 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -140,6 +140,7 @@ static const char* _rava_opcode_name(RavaOpCode_e opcode) { case RAVA_OP_RETURN_VOID: return "RETURN_VOID"; case RAVA_OP_NEW: return "NEW"; case RAVA_OP_NEW_ARRAY: return "NEW_ARRAY"; + case RAVA_OP_NEW_ARRAY_OF_ARRAYS: return "NEW_ARRAY_OF_ARRAYS"; case RAVA_OP_ARRAY_LENGTH: return "ARRAY_LENGTH"; case RAVA_OP_LOAD_ARRAY: return "LOAD_ARRAY"; case RAVA_OP_STORE_ARRAY: return "STORE_ARRAY"; diff --git a/ir/ir.h b/ir/ir.h index 8156ad8..b938017 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -61,6 +61,7 @@ typedef enum { RAVA_OP_NEW, RAVA_OP_NEW_ARRAY, + RAVA_OP_NEW_ARRAY_OF_ARRAYS, RAVA_OP_ARRAY_LENGTH, RAVA_OP_GET_FIELD, RAVA_OP_PUT_FIELD, diff --git a/ir/ir_gen.c b/ir/ir_gen.c index e53f809..62c41e0 100644 --- a/ir/ir_gen.c +++ b/ir/ir_gen.c @@ -7,6 +7,13 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr); static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt); +static bool _rava_has_modifier(RavaModifier_e *mods, size_t count, RavaModifier_e mod) { + for (size_t i = 0; i < count; i++) { + if (mods[i] == mod) return true; + } + return false; +} + static void _rava_ir_clear_locals(RavaIRGenerator_t *gen) { RavaLocalVar_t *current = gen->locals; while (current) { @@ -286,8 +293,12 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr) } } _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); + if (strcmp(expr->data.member_access.member, "length") == 0) { + instr.opcode = RAVA_OP_ARRAY_LENGTH; + } else { + instr.opcode = RAVA_OP_GET_FIELD; + instr.operand.field.field_name = strdup(expr->data.member_access.member); + } _rava_ir_emit(gen, instr); break; @@ -300,11 +311,94 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr) case RAVA_AST_NEW_EXPR: if (expr->data.new_expr.type && expr->data.new_expr.type->data.type.is_array) { - if (expr->data.new_expr.arguments_count > 0) { + if (expr->data.new_expr.arguments_count == 1) { _rava_ir_gen_expression(gen, expr->data.new_expr.arguments[0]); + instr.opcode = RAVA_OP_NEW_ARRAY; + _rava_ir_emit(gen, instr); + } else if (expr->data.new_expr.arguments_count >= 2) { + int saved_next_local = gen->next_local; + + _rava_ir_gen_expression(gen, expr->data.new_expr.arguments[0]); + instr.opcode = RAVA_OP_NEW_ARRAY_OF_ARRAYS; + _rava_ir_emit(gen, instr); + + int outer_var = gen->next_local++; + instr.opcode = RAVA_OP_STORE_LOCAL; + instr.operand.var.index = outer_var; + _rava_ir_emit(gen, instr); + + int loop_var = gen->next_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 = loop_var; + _rava_ir_emit(gen, instr); + + int loop_start = rava_instruction_list_new_label(gen->current_method->instructions); + int loop_end = rava_instruction_list_new_label(gen->current_method->instructions); + + instr.opcode = RAVA_OP_LABEL; + instr.operand.label_id = loop_start; + _rava_ir_emit(gen, instr); + + instr.opcode = RAVA_OP_LOAD_LOCAL; + instr.operand.var.index = loop_var; + _rava_ir_emit(gen, instr); + _rava_ir_gen_expression(gen, expr->data.new_expr.arguments[0]); + instr.opcode = RAVA_OP_LT; + _rava_ir_emit(gen, instr); + instr.opcode = RAVA_OP_JUMP_IF_FALSE; + instr.operand.label_id = loop_end; + _rava_ir_emit(gen, instr); + + instr.opcode = RAVA_OP_LOAD_LOCAL; + instr.operand.var.index = outer_var; + _rava_ir_emit(gen, instr); + instr.opcode = RAVA_OP_LOAD_LOCAL; + instr.operand.var.index = loop_var; + _rava_ir_emit(gen, instr); + _rava_ir_gen_expression(gen, expr->data.new_expr.arguments[1]); + instr.opcode = RAVA_OP_NEW_ARRAY; + _rava_ir_emit(gen, instr); + instr.opcode = RAVA_OP_STORE_ARRAY; + _rava_ir_emit(gen, instr); + + instr.opcode = RAVA_OP_LOAD_LOCAL; + instr.operand.var.index = loop_var; + _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 = loop_var; + _rava_ir_emit(gen, instr); + + instr.opcode = RAVA_OP_JUMP; + instr.operand.label_id = loop_start; + _rava_ir_emit(gen, instr); + + instr.opcode = RAVA_OP_LABEL; + instr.operand.label_id = loop_end; + _rava_ir_emit(gen, instr); + + instr.opcode = RAVA_OP_LOAD_LOCAL; + instr.operand.var.index = outer_var; + _rava_ir_emit(gen, instr); + + if (gen->next_local > gen->current_method->local_count) { + gen->current_method->local_count = gen->next_local; + } + gen->next_local = saved_next_local; + } else { + instr.opcode = RAVA_OP_LOAD_CONST; + instr.operand.int_value = 0; + _rava_ir_emit(gen, instr); + instr.opcode = RAVA_OP_NEW_ARRAY; + _rava_ir_emit(gen, instr); } - instr.opcode = RAVA_OP_NEW_ARRAY; - _rava_ir_emit(gen, instr); } else if (expr->data.new_expr.type) { instr.opcode = RAVA_OP_NEW; instr.operand.call.class_name = strdup(expr->data.new_expr.type->data.type.type_name); @@ -612,6 +706,17 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr) instr.opcode = RAVA_OP_PRINT; } _rava_ir_emit(gen, instr); + } else if (expr->data.call.callee->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(""); + instr.operand.call.arg_count = expr->data.call.arguments_count; + _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) { @@ -1178,7 +1283,15 @@ static void _rava_ir_gen_method(RavaIRGenerator_t *gen, RavaASTNode_t *method_no rava_symbol_table_exit_scope(gen->analyzer->symbol_table); - method->local_count = gen->next_local; + if (return_type && strcmp(return_type->name, "void") == 0) { + RavaInstruction_t ret_instr = {0}; + ret_instr.opcode = RAVA_OP_RETURN_VOID; + _rava_ir_emit(gen, ret_instr); + } + + if (gen->next_local > method->local_count) { + method->local_count = gen->next_local; + } rava_class_add_method(gen->current_class, method); gen->current_method = NULL; } @@ -1206,7 +1319,9 @@ static void _rava_ir_gen_constructor(RavaIRGenerator_t *gen, RavaASTNode_t *ctor ret_instr.opcode = RAVA_OP_RETURN_VOID; _rava_ir_emit(gen, ret_instr); - method->local_count = gen->next_local; + if (gen->next_local > method->local_count) { + method->local_count = gen->next_local; + } rava_class_add_method(gen->current_class, method); gen->current_method = NULL; } @@ -1222,6 +1337,48 @@ static void _rava_ir_gen_class(RavaIRGenerator_t *gen, RavaASTNode_t *class_node rava_symbol_table_enter_scope(gen->analyzer->symbol_table, class_node->data.class_decl.name); + bool has_static_init = false; + for (size_t i = 0; i < class_node->children_count; i++) { + RavaASTNode_t *child = class_node->children[i]; + if (child->type == RAVA_AST_FIELD_DECL && + child->data.field_decl.initializer && + _rava_has_modifier(child->data.field_decl.modifiers, + child->data.field_decl.modifiers_count, + RAVA_MODIFIER_STATIC)) { + has_static_init = true; + break; + } + } + + if (has_static_init) { + RavaMethod_t *clinit = rava_method_create("", NULL); + gen->current_method = clinit; + gen->next_local = 0; + _rava_ir_clear_locals(gen); + + RavaInstruction_t instr = {0}; + for (size_t i = 0; i < class_node->children_count; i++) { + RavaASTNode_t *child = class_node->children[i]; + if (child->type == RAVA_AST_FIELD_DECL && + child->data.field_decl.initializer && + _rava_has_modifier(child->data.field_decl.modifiers, + child->data.field_decl.modifiers_count, + RAVA_MODIFIER_STATIC)) { + _rava_ir_gen_expression(gen, child->data.field_decl.initializer); + instr.opcode = RAVA_OP_STORE_STATIC; + instr.operand.field.class_name = strdup(class_node->data.class_decl.name); + instr.operand.field.field_name = strdup(child->data.field_decl.name); + _rava_ir_emit(gen, instr); + } + } + + instr.opcode = RAVA_OP_RETURN_VOID; + _rava_ir_emit(gen, instr); + clinit->local_count = gen->next_local; + rava_class_add_method(gen->current_class, clinit); + gen->current_method = NULL; + } + for (size_t i = 0; i < class_node->children_count; i++) { RavaASTNode_t *child = class_node->children[i]; diff --git a/parser/parser_declarations.c b/parser/parser_declarations.c index 145abe1..6ffa52f 100644 --- a/parser/parser_declarations.c +++ b/parser/parser_declarations.c @@ -122,7 +122,8 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) { _rava_parser_parse_modifiers(parser, &member_modifiers, &member_modifiers_count); if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER) && - strcmp(parser->current_token->lexeme, class_decl->data.class_decl.name) == 0) { + strcmp(parser->current_token->lexeme, class_decl->data.class_decl.name) == 0 && + parser->peek_token && parser->peek_token->type == RAVA_TOKEN_LPAREN) { RavaASTNode_t *constructor = rava_ast_node_create(RAVA_AST_CONSTRUCTOR_DECL, parser->current_token->line, diff --git a/runtime/runtime.c b/runtime/runtime.c index a81465c..715fcf2 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -187,6 +187,10 @@ RavaArray_t* rava_array_create(RavaValueType_e element_type, size_t length) { case RAVA_VAL_BOOLEAN: array->data = calloc(length, sizeof(bool)); break; + case RAVA_VAL_ARRAY: + case RAVA_VAL_OBJECT: + array->data = calloc(length, sizeof(RavaValue_t)); + break; default: array->data = calloc(length, sizeof(void*)); break; @@ -216,6 +220,16 @@ int32_t rava_array_get_int(RavaArray_t *array, size_t index) { return ((int32_t*)array->data)[index]; } +void rava_array_set_value(RavaArray_t *array, size_t index, RavaValue_t value) { + if (!array || !array->data || index >= array->length) return; + ((RavaValue_t*)array->data)[index] = value; +} + +RavaValue_t rava_array_get_value(RavaArray_t *array, size_t index) { + if (!array || !array->data || index >= array->length) return rava_value_null(); + return ((RavaValue_t*)array->data)[index]; +} + size_t rava_array_length(RavaArray_t *array) { if (!array) return 0; return array->length; @@ -1119,6 +1133,19 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R break; } + case RAVA_OP_NEW_ARRAY_OF_ARRAYS: { + RavaValue_t length_val = rava_stack_pop(stack); + int32_t length = rava_value_as_int(length_val); + if (length < 0) length = 0; + RavaArray_t *array = rava_array_create(RAVA_VAL_ARRAY, (size_t)length); + if (array) { + rava_stack_push(stack, rava_value_array(array)); + } else { + rava_stack_push(stack, rava_value_null()); + } + break; + } + case RAVA_OP_GET_FIELD: { RavaValue_t obj_val = rava_stack_pop(stack); if (obj_val.type == RAVA_VAL_OBJECT && obj_val.data.object_val) { @@ -1155,8 +1182,13 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R RavaValue_t array_val = rava_stack_pop(stack); if (array_val.type == RAVA_VAL_ARRAY) { int32_t index = rava_value_as_int(index_val); - int32_t value = rava_array_get_int(array_val.data.array_val, (size_t)index); - rava_stack_push(stack, rava_value_int(value)); + RavaArray_t *arr = array_val.data.array_val; + if (arr->element_type == RAVA_VAL_ARRAY || arr->element_type == RAVA_VAL_OBJECT) { + rava_stack_push(stack, rava_array_get_value(arr, (size_t)index)); + } else { + int32_t value = rava_array_get_int(arr, (size_t)index); + rava_stack_push(stack, rava_value_int(value)); + } } else { rava_stack_push(stack, rava_value_int(0)); } @@ -1169,8 +1201,13 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R RavaValue_t array_val = rava_stack_pop(stack); if (array_val.type == RAVA_VAL_ARRAY) { int32_t index = rava_value_as_int(index_val); - int32_t value = rava_value_as_int(value_val); - rava_array_set_int(array_val.data.array_val, (size_t)index, value); + RavaArray_t *arr = array_val.data.array_val; + if (arr->element_type == RAVA_VAL_ARRAY || arr->element_type == RAVA_VAL_OBJECT) { + rava_array_set_value(arr, (size_t)index, value_val); + } else { + int32_t value = rava_value_as_int(value_val); + rava_array_set_int(arr, (size_t)index, value); + } } break; } @@ -1633,7 +1670,7 @@ static bool _rava_vm_execute_fast(RavaVM_t *vm, RavaCallFrame_t *frame) { &&op_jump, &&op_jump_if_true, &&op_jump_if_false, &&op_label, &&op_call, &&op_call_static, &&op_call_virtual, &&op_call_super, &&op_call_native, &&op_return, &&op_return_void, - &&op_new, &&op_new_array, &&op_array_length, &&op_get_field, &&op_put_field, + &&op_new, &&op_new_array, &&op_new_array_of_arrays, &&op_array_length, &&op_get_field, &&op_put_field, &&op_cast, &&op_instanceof, &&op_throw, &&op_try_begin, &&op_try_end, &&op_pop, &&op_dup, &&op_print, &&op_println, @@ -1739,6 +1776,10 @@ op_load_array: { case RAVA_VAL_LONG: STACK_PUSH_LONG(stack, ((int64_t*)arr.data.array_val->data)[index]); break; + case RAVA_VAL_ARRAY: + case RAVA_VAL_OBJECT: + STACK_PUSH(stack, ((RavaValue_t*)arr.data.array_val->data)[index]); + break; default: STACK_PUSH_INT(stack, ((int32_t*)arr.data.array_val->data)[index]); break; @@ -1786,6 +1827,10 @@ op_store_array: { case RAVA_VAL_LONG: ((int64_t*)arr.data.array_val->data)[index] = rava_value_as_long(value); break; + case RAVA_VAL_ARRAY: + case RAVA_VAL_OBJECT: + ((RavaValue_t*)arr.data.array_val->data)[index] = value; + break; default: ((int32_t*)arr.data.array_val->data)[index] = rava_value_as_int(value); break; @@ -2179,6 +2224,14 @@ op_new_array: { DISPATCH(); } +op_new_array_of_arrays: { + RavaValue_t size_val = STACK_POP(stack); + size_t size = (size_t)rava_value_as_int(size_val); + RavaArray_t *array = rava_array_create(RAVA_VAL_ARRAY, size); + STACK_PUSH(stack, rava_value_array(array)); + DISPATCH(); +} + op_array_length: { RavaValue_t arr = STACK_POP(stack); if (arr.type == RAVA_VAL_ARRAY && arr.data.array_val) { @@ -2866,7 +2919,7 @@ static bool _rava_vm_execute_ultrafast(RavaVM_t *vm, RavaMethod_t *entry_method) &&uf_jump, &&uf_jump_if_true, &&uf_jump_if_false, &&uf_label, &&uf_call, &&uf_call_static, &&uf_call_virtual, &&uf_call_super, &&uf_call_native, &&uf_return, &&uf_return_void, - &&uf_new, &&uf_new_array, &&uf_array_length, &&uf_get_field, &&uf_put_field, + &&uf_new, &&uf_new_array, &&uf_new_array_of_arrays, &&uf_array_length, &&uf_get_field, &&uf_put_field, &&uf_cast, &&uf_instanceof, &&uf_throw, &&uf_try_begin, &&uf_try_end, &&uf_pop, &&uf_dup, &&uf_print, &&uf_println, @@ -3317,6 +3370,14 @@ uf_new_array: { UF_DISPATCH(); } +uf_new_array_of_arrays: { + RavaNanboxValue_t size_val = UF_POP(); + int32_t size = rava_nanbox_to_int(size_val); + RavaArray_t *arr = rava_array_create(RAVA_VAL_ARRAY, size > 0 ? (size_t)size : 0); + UF_PUSH(rava_nanbox_array(arr)); + UF_DISPATCH(); +} + uf_array_length: { RavaNanboxValue_t arr_val = UF_POP(); RavaArray_t *arr = rava_nanbox_as_array(arr_val); @@ -3330,8 +3391,13 @@ uf_load_array: { RavaArray_t *arr = rava_nanbox_as_array(arr_val); int32_t i = rava_nanbox_to_int(idx); if (arr && i >= 0 && (size_t)i < arr->length) { - int32_t val = rava_array_get_int(arr, (size_t)i); - UF_PUSH(rava_nanbox_int(val)); + if (arr->element_type == RAVA_VAL_ARRAY || arr->element_type == RAVA_VAL_OBJECT) { + RavaValue_t v = rava_array_get_value(arr, (size_t)i); + UF_PUSH(rava_value_to_nanbox(v)); + } else { + int32_t val = rava_array_get_int(arr, (size_t)i); + UF_PUSH(rava_nanbox_int(val)); + } } else { UF_PUSH(rava_nanbox_int(0)); } @@ -3345,7 +3411,11 @@ uf_store_array: { RavaArray_t *arr = rava_nanbox_as_array(arr_val); int32_t i = rava_nanbox_to_int(idx); if (arr && i >= 0 && (size_t)i < arr->length) { - rava_array_set_int(arr, (size_t)i, rava_nanbox_to_int(val)); + if (arr->element_type == RAVA_VAL_ARRAY || arr->element_type == RAVA_VAL_OBJECT) { + rava_array_set_value(arr, (size_t)i, rava_nanbox_to_value(val)); + } else { + rava_array_set_int(arr, (size_t)i, rava_nanbox_to_int(val)); + } } UF_DISPATCH(); } @@ -3944,7 +4014,43 @@ uf_done: } #endif +static bool _rava_vm_run_static_initializers(RavaVM_t *vm) { + for (size_t c = 0; c < vm->program->class_count; c++) { + RavaClass_t *cls = vm->program->classes[c]; + for (size_t m = 0; m < cls->method_count; m++) { + RavaMethod_t *method = cls->methods[m]; + if (strcmp(method->name, "") == 0) { + RavaCallFrame_t *frame = rava_call_frame_create(method); + rava_call_stack_push(vm->call_stack, frame); +#ifdef __GNUC__ + if (!_rava_vm_execute_fast(vm, frame)) { + return false; + } +#else + while (frame->pc < frame->method->instructions->count) { + RavaInstruction_t *instr = &frame->method->instructions->instructions[frame->pc]; + if (instr->opcode == RAVA_OP_RETURN || instr->opcode == RAVA_OP_RETURN_VOID) { + break; + } + frame->pc++; + if (!_rava_vm_execute_instruction(vm, frame, instr)) { + return false; + } + } +#endif + rava_call_stack_pop(vm->call_stack); + rava_call_frame_destroy(frame); + } + } + } + return true; +} + bool rava_vm_execute(RavaVM_t *vm, const char *class_name, const char *method_name) { + if (!_rava_vm_run_static_initializers(vm)) { + return false; + } + RavaMethod_t *method = _rava_vm_find_method_cached(vm, class_name, method_name); if (!method) { vm->had_error = true; diff --git a/runtime/runtime.h b/runtime/runtime.h index b8ea80e..b048989 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -133,6 +133,8 @@ RavaArray_t* rava_array_create(RavaValueType_e element_type, size_t length); void rava_array_destroy(RavaArray_t *array); void rava_array_set_int(RavaArray_t *array, size_t index, int32_t value); int32_t rava_array_get_int(RavaArray_t *array, size_t index); +void rava_array_set_value(RavaArray_t *array, size_t index, RavaValue_t value); +RavaValue_t rava_array_get_value(RavaArray_t *array, size_t index); size_t rava_array_length(RavaArray_t *array); RavaObject_t* rava_object_create(const char *class_name);