diff --git a/include/common/fzl_builtins.h b/include/common/fzl_builtins.h index 678de31..a24c6bd 100644 --- a/include/common/fzl_builtins.h +++ b/include/common/fzl_builtins.h @@ -3,7 +3,8 @@ typedef enum { - FZL_BUILTIN_PRINTLINE // Print message in arg with newline at end + FZL_BUILTIN_PRINTLINE, // Print message in arg with newline at end + FZL_BUILTIN_EXIT, // Exit program with code specified in arg } fzl_builtin_t; #endif // FZL_BUILTINS_H diff --git a/src/compiler/fzl_walker.c b/src/compiler/fzl_walker.c index 6095168..6537e88 100644 --- a/src/compiler/fzl_walker.c +++ b/src/compiler/fzl_walker.c @@ -754,6 +754,30 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node) } current_res = (fzl_walk_res_t){.type = FZL_TYPE_NULL, .error = false}; } + else if (strcmp(node->token->value, "exit") == 0) + { + if (node->call.args_count > 0) + { + for (size_t i = 0; i < node->call.args_count; i++) + { + fzl_walk_res_t res = walk(walker, node->call.args[i]); + if (res.error) + return res; + } + + push_op(walker, FZL_OPCODE_CALL_BUILTIN); + push_word(walker, FZL_BUILTIN_EXIT); + if (node->call.args_count < 1) + { + snprintf(wlast_err, sizeof(wlast_err), + "'%s': 'exit' call with zero arguments at %ld:%ld", + node->token->filename, node->token->ln, node->token->cn); + return (fzl_walk_res_t){.error = true, .error_msg = wlast_err}; + } + current_res = + (fzl_walk_res_t){.type = FZL_TYPE_NULL, .error = false}; + } + } else { if (node->call.callee->type == FZL_NODETYPE_IDENTIFIER) @@ -778,8 +802,9 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node) if (!found) { snprintf(wlast_err, sizeof(wlast_err), - "call to unknown function '%s'", - (char *)node->token->value); + "'%s': call to unknown function '%s' at %ld:%ld", + node->token->filename, (char *)node->token->value, + node->token->ln, node->token->cn); return (fzl_walk_res_t){.error = true, .error_msg = wlast_err}; } diff --git a/src/vm/fzl_vm.c b/src/vm/fzl_vm.c index 1cce290..d9f1d02 100644 --- a/src/vm/fzl_vm.c +++ b/src/vm/fzl_vm.c @@ -538,8 +538,8 @@ int fzl_vm_run(fzl_vm_t *vm) return -1; } - fzl_value_t llt = vm->dstack[--vm->dtop]; fzl_value_t rlt = vm->dstack[--vm->dtop]; + fzl_value_t llt = vm->dstack[--vm->dtop]; vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_BOOL, .as.b = llt.as.u < rlt.as.u}; break; @@ -769,6 +769,11 @@ int fzl_vm_run(fzl_vm_t *vm) else if (arg.type == FZL_TYPE_OBJECT) print_object(arg.as.obj); } + else if (fn_id == FZL_BUILTIN_EXIT) + { + fzl_value_t arg = vm->dstack[--vm->dtop]; + exit(arg.as.i); + } else { snprintf(last_err, sizeof(last_err),