Update, multi dimentional arrays.
Some checks failed
CI / Optimization Infrastructure Tests (push) Failing after 12s
CI / Unit Tests (push) Failing after 25s
CI / Integration Tests (push) Has been skipped
CI / Performance Benchmark (push) Has been skipped

This commit is contained in:
retoor 2025-12-03 14:08:55 +01:00
parent 7c4f92484a
commit a3cad2b743
7 changed files with 301 additions and 21 deletions

View File

@ -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 ==="

View File

@ -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";

View File

@ -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,

View File

@ -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);
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);
}
} 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("<init>");
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);
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);
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("<clinit>", 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];

View File

@ -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,

View File

@ -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);
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);
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(array_val.data.array_val, (size_t)index, value);
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) {
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,8 +3411,12 @@ 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) {
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, "<clinit>") == 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;

View File

@ -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);