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