feat: implement support for multi-dimensional array initialization and access
This commit is contained in:
+115
-9
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user