feat: implement support for multi-dimensional array initialization and access

This commit is contained in:
2025-12-03 13:08:55 +00:00
parent 6dfbe4a4d0
commit 43103e7120
7 changed files with 301 additions and 21 deletions
+115 -9
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);
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, "<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;
+2
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);