|
|
@@ -284,6 +284,56 @@ void l2_vm_run(struct l2_vm *vm) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// The 'call_func' function assumes that all relevant values have been popped off |
|
|
|
// the stack, so that the return value can be pushed to the top of the stack |
|
|
|
// straight away |
|
|
|
static void call_func( |
|
|
|
struct l2_vm *vm, l2_word func_id, |
|
|
|
l2_word argc, l2_word *argv) { |
|
|
|
l2_word stack_base = vm->sptr; |
|
|
|
|
|
|
|
struct l2_vm_value *func = &vm->values[func_id]; |
|
|
|
enum l2_value_type typ = l2_vm_value_type(func); |
|
|
|
|
|
|
|
// C functions are called differently from language functions |
|
|
|
if (typ == L2_VAL_TYPE_CFUNCTION) { |
|
|
|
vm->stack[vm->sptr++] = func->cfunc(vm, argc, argv); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Don't interpret a non-function as a function |
|
|
|
if (typ != L2_VAL_TYPE_FUNCTION) { |
|
|
|
vm->stack[vm->sptr++] = l2_vm_error(vm, "Attempt to call non-function"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
l2_word arr_id = alloc_val(vm); |
|
|
|
vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY; |
|
|
|
vm->values[arr_id].array = malloc( |
|
|
|
sizeof(struct l2_vm_array) + sizeof(l2_word) * argc); |
|
|
|
struct l2_vm_array *arr = vm->values[arr_id].array; |
|
|
|
arr->len = argc; |
|
|
|
arr->size = argc; |
|
|
|
|
|
|
|
for (l2_word i = 0; i < argc; ++i) { |
|
|
|
arr->data[i] = argv[i]; |
|
|
|
} |
|
|
|
|
|
|
|
vm->stack[vm->sptr++] = arr_id; |
|
|
|
|
|
|
|
l2_word ns_id = alloc_val(vm); |
|
|
|
func = &vm->values[func_id]; // func might be stale after alloc |
|
|
|
vm->values[ns_id].extra.ns_parent = func->func.ns; |
|
|
|
vm->values[ns_id].ns = NULL; |
|
|
|
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; |
|
|
|
vm->fstack[vm->fsptr].ns = ns_id; |
|
|
|
vm->fstack[vm->fsptr].retptr = vm->iptr; |
|
|
|
vm->fstack[vm->fsptr].sptr = stack_base; |
|
|
|
vm->fsptr += 1; |
|
|
|
|
|
|
|
vm->iptr = func->func.pos; |
|
|
|
} |
|
|
|
|
|
|
|
void l2_vm_step(struct l2_vm *vm) { |
|
|
|
enum l2_opcode opcode = (enum l2_opcode)vm->ops[vm->iptr++]; |
|
|
|
|
|
|
@@ -326,48 +376,7 @@ void l2_vm_step(struct l2_vm *vm) { |
|
|
|
l2_word *argv = vm->stack + vm->sptr; |
|
|
|
|
|
|
|
l2_word func_id = vm->stack[--vm->sptr]; |
|
|
|
struct l2_vm_value *func = &vm->values[func_id]; |
|
|
|
|
|
|
|
l2_word stack_base = vm->sptr; |
|
|
|
enum l2_value_type typ = l2_vm_value_type(func); |
|
|
|
|
|
|
|
// C functions are called differently from language functions |
|
|
|
if (typ == L2_VAL_TYPE_CFUNCTION) { |
|
|
|
vm->stack[vm->sptr++] = func->cfunc(vm, argc, argv); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// Don't interpret a non-function as a function |
|
|
|
if (typ != L2_VAL_TYPE_FUNCTION) { |
|
|
|
vm->stack[vm->sptr++] = l2_vm_error(vm, "Attempt to call non-function"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
l2_word arr_id = alloc_val(vm); |
|
|
|
vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY; |
|
|
|
vm->values[arr_id].array = malloc( |
|
|
|
sizeof(struct l2_vm_array) + sizeof(l2_word) * argc); |
|
|
|
struct l2_vm_array *arr = vm->values[arr_id].array; |
|
|
|
arr->len = argc; |
|
|
|
arr->size = argc; |
|
|
|
|
|
|
|
for (l2_word i = 0; i < argc; ++i) { |
|
|
|
arr->data[i] = argv[i]; |
|
|
|
} |
|
|
|
|
|
|
|
vm->stack[vm->sptr++] = arr_id; |
|
|
|
|
|
|
|
l2_word ns_id = alloc_val(vm); |
|
|
|
func = &vm->values[func_id]; // func might be stale after alloc |
|
|
|
vm->values[ns_id].extra.ns_parent = func->func.ns; |
|
|
|
vm->values[ns_id].ns = NULL; |
|
|
|
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; |
|
|
|
vm->fstack[vm->fsptr].ns = ns_id; |
|
|
|
vm->fstack[vm->fsptr].retptr = vm->iptr; |
|
|
|
vm->fstack[vm->fsptr].sptr = stack_base; |
|
|
|
vm->fsptr += 1; |
|
|
|
|
|
|
|
vm->iptr = func->func.pos; |
|
|
|
call_func(vm, func_id, argc, argv); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
@@ -583,47 +592,8 @@ void l2_vm_step(struct l2_vm *vm) { |
|
|
|
l2_word func_id = vm->stack[--vm->sptr]; |
|
|
|
l2_word lhs = vm->stack[--vm->sptr]; |
|
|
|
|
|
|
|
struct l2_vm_value *func = &vm->values[func_id]; |
|
|
|
|
|
|
|
l2_word stack_base = vm->sptr; |
|
|
|
enum l2_value_type typ = l2_vm_value_type(func); |
|
|
|
|
|
|
|
// C functions are called differently from language functions |
|
|
|
if (typ == L2_VAL_TYPE_CFUNCTION) { |
|
|
|
l2_word argv[] = { lhs, rhs }; |
|
|
|
vm->stack[vm->sptr++] = func->cfunc(vm, 2, argv); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// Don't interpret a non-function as a function |
|
|
|
if (typ != L2_VAL_TYPE_FUNCTION) { |
|
|
|
vm->stack[vm->sptr++] = l2_vm_error(vm, "Attempt to call non-function"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
l2_word arr_id = alloc_val(vm); |
|
|
|
vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY; |
|
|
|
vm->values[arr_id].array = malloc( |
|
|
|
sizeof(struct l2_vm_array) + sizeof(l2_word) * 2); |
|
|
|
struct l2_vm_array *arr = vm->values[arr_id].array; |
|
|
|
arr->len = 2; |
|
|
|
arr->size = 2; |
|
|
|
arr->data[0] = lhs; |
|
|
|
arr->data[1] = rhs; |
|
|
|
|
|
|
|
vm->stack[vm->sptr++] = arr_id; |
|
|
|
|
|
|
|
l2_word ns_id = alloc_val(vm); |
|
|
|
func = &vm->values[func_id]; // func might be stale after alloc |
|
|
|
vm->values[ns_id].extra.ns_parent = func->func.ns; |
|
|
|
vm->values[ns_id].ns = NULL; |
|
|
|
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; |
|
|
|
vm->fstack[vm->fsptr].ns = ns_id; |
|
|
|
vm->fstack[vm->fsptr].retptr = vm->iptr; |
|
|
|
vm->fstack[vm->fsptr].sptr = stack_base; |
|
|
|
vm->fsptr += 1; |
|
|
|
|
|
|
|
vm->iptr = func->func.pos; |
|
|
|
l2_word argv[] = {lhs, rhs}; |
|
|
|
call_func(vm, func_id, 2, argv); |
|
|
|
} |
|
|
|
break; |
|
|
|
|