diff options
| author | iamcheeseman <[email protected]> | 2026-04-16 16:13:52 -0400 |
|---|---|---|
| committer | iamcheeseman <[email protected]> | 2026-04-16 16:13:52 -0400 |
| commit | eb0e4255e9eb878b7a17830b5be06a71add3b34e (patch) | |
| tree | 2714b598f43518348300f5dd5eedc2e5bd92a847 | |
| parent | 7663596a72347d8dab936c6503002d95149c04c9 (diff) | |
microscript: better runtime errors
| -rw-r--r-- | uscript/uscript.c | 6 | ||||
| -rw-r--r-- | uscript/uscript.h | 1 | ||||
| -rw-r--r-- | uscript/val.h | 3 | ||||
| -rw-r--r-- | uscript/vm.c | 77 |
4 files changed, 56 insertions, 31 deletions
diff --git a/uscript/uscript.c b/uscript/uscript.c index 02dc69e..008bcbe 100644 --- a/uscript/uscript.c +++ b/uscript/uscript.c @@ -58,7 +58,7 @@ void core_range_next(int argc) void core_range(int argc) { if (vm_get(1).type != VAL_NUM || vm_get(2).type != VAL_NUM) - log_fatal(1, "core:range expected two numbers"); + us_err("core:range expected two numbers"); struct us_str *str = copy_str("rangenext", -1); struct us_cfunc *cfunc = create_cfunc(str, core_range_next, 0); @@ -74,7 +74,7 @@ void arr_add(int argc) (void)argc; if (vm_get(0).type != VAL_ARR) - log_fatal(1, "arr:add expected an array"); + us_err("arr:add expected an array"); struct us_arr *arr = get_arr(vm_get(0)); da_append(struct us_val, &arr->e, vm_get(1)); @@ -105,7 +105,7 @@ void arr_iter(int argc) (void)argc; if (vm_get(0).type != VAL_ARR) - log_fatal(1, "arr:iter expected an array"); + us_err("arr:iter expected an array"); struct us_str *str = copy_str("arr:iternext", -1); struct us_cfunc *cfunc = create_cfunc(str, arr_iter_next, 0); diff --git a/uscript/uscript.h b/uscript/uscript.h index a7efced..1973c7d 100644 --- a/uscript/uscript.h +++ b/uscript/uscript.h @@ -12,6 +12,7 @@ void us_load_file(const char *file); void us_load_src(const char *src); void us_exec(struct us_func *func); +void us_err(const char *msg, ...); void us_set_cfunc(const char *c_name, us_cfunc_sig c, int argc); diff --git a/uscript/val.h b/uscript/val.h index 8ea91dd..5deb64c 100644 --- a/uscript/val.h +++ b/uscript/val.h @@ -83,7 +83,8 @@ struct us_proto { const struct us_str *name; struct us_val constants[UINT8_MAX]; u8 *bytecode; // dyn_arr - int* upval_locs; + int *lines; // dyn_arr + int *upval_locs; int upvalc; int argc; bool is_variadic; diff --git a/uscript/vm.c b/uscript/vm.c index 9fbd8c0..c381112 100644 --- a/uscript/vm.c +++ b/uscript/vm.c @@ -1,6 +1,7 @@ #include "vm.h" #include <math.h> +#include <stdarg.h> #include <string.h> #include "dyn_arr.h" @@ -14,6 +15,7 @@ void init_vm(void) vm.objs = da_create(struct us_val, 128); vm.gstack = da_create(struct global, 128); vm.cf = vm.cf_stack; + vm.cf->stackbot = NULL; vm.stacktop = vm.stack; } @@ -28,6 +30,32 @@ void deinit_vm(void) da_free(vm.gstack); } +void us_err(const char *msg, ...) +{ + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + putc('\n', stderr); + + for (struct call_frame *cf = vm.cf; vm.cf > vm.cf_stack; cf--) { + if (!cf->stackbot) + break; + if (cf->func.type == VAL_FUNC) { + struct us_func *func = get_func(cf->func); + fprintf(stderr, "\tby %s()\n", func->proto->name->chars); + } else if (cf->func.type == VAL_CFUNC) { + struct us_cfunc *cfunc = get_cfunc(cf->func); + fprintf(stderr, "\tby [c] %s()\n", cfunc->name->chars); + } else { + fprintf(stderr, "\tunknown\n"); + } + } + + // TODO: Replace with a longjmp + exit(1); +} + static bool as_bool(struct us_val v) { @@ -76,14 +104,13 @@ void index_val(struct us_val idx_val, struct us_val idxee_val) switch (idxee_val.type) { case VAL_ARR: { if (idx_val.type != VAL_NUM) - log_fatal(1, "arrays must be indexed by numbers"); + us_err("arrays must be indexed by numbers"); int idx = (int)get_num(idx_val); struct us_arr *arr = get_arr(idxee_val); if (idx < 0) idx += da_len(arr->e); if (idx < 0 || idx >= da_len(arr->e)) { - log_fatal( - 1, + us_err( "index out of range (%d/%d)", idx, da_len(arr->e) - 1 @@ -94,14 +121,13 @@ void index_val(struct us_val idx_val, struct us_val idxee_val) } case VAL_STR: { if (idx_val.type != VAL_NUM) - log_fatal(1, "strings must be indexed by numbers"); + us_err("strings must be indexed by numbers"); int idx = (int)get_num(idx_val); struct us_str *str = get_str(idxee_val); if (idx < 0) idx += str->len; if (idx < 0 || (size_t)idx >= str->len) { - log_fatal( - 1, + us_err( "index out of range (%d/%d)", idx, str->len - 1 @@ -111,7 +137,7 @@ void index_val(struct us_val idx_val, struct us_val idxee_val) break; } default: - log_fatal(1, "cannot index that value"); + us_err("cannot index that value"); break; } } @@ -123,8 +149,7 @@ void call_val(struct us_val callee, int argc) case VAL_FUNC: { struct us_func *func = get_func(callee); if (argc != func->proto->argc) { - log_fatal( - 1, + us_err( "wrong number of arguments to '%s()' (%d/%d)", func->proto->name->chars, argc, @@ -137,8 +162,7 @@ void call_val(struct us_val callee, int argc) case VAL_CFUNC: { struct us_cfunc *cfunc = get_cfunc(callee); if (argc != cfunc->argc) { - log_fatal( - 1, + us_err( "wrong number of arguments to '%s()' (%d/%d)", cfunc->name->chars, argc, @@ -157,7 +181,7 @@ void call_val(struct us_val callee, int argc) break; } default: - log_fatal(1, "cannot call that value"); + us_err("cannot call that value"); break; } } @@ -276,16 +300,15 @@ void us_exec(struct us_func *func) struct us_val idx_val = vm_pop(); struct us_val arr_val = vm_pop(); if (idx_val.type != VAL_NUM) - log_fatal(1, "index type must be number"); + us_err("index type must be number"); if (arr_val.type != VAL_ARR) - log_fatal(1, "only arrays can be indexed"); + us_err("only arrays can be indexed"); int idx = (int)get_num(idx_val); struct us_arr *arr = get_arr(arr_val); if (idx < 0) idx += da_len(arr->e); if (idx < 0 || idx >= da_len(arr->e)) { - log_fatal( - 1, + us_err( "index out of range (%d/%d)", idx, da_len(arr->e) - 1 @@ -304,7 +327,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_num(get_num(a) + get_num(b))); break; } @@ -312,7 +335,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_num(get_num(a) - get_num(b))); break; } @@ -320,7 +343,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_num(get_num(a) * get_num(b))); break; } @@ -328,7 +351,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_num(get_num(a) / get_num(b))); break; } @@ -336,7 +359,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_num(fmod(get_num(a), get_num(b)))); break; } @@ -344,7 +367,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_bool(get_num(a) > get_num(b))); break; } @@ -352,7 +375,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_bool(get_num(a) >= get_num(b))); break; } @@ -360,7 +383,7 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_bool(get_num(a) < get_num(b))); break; } @@ -368,14 +391,14 @@ void us_exec(struct us_func *func) struct us_val b = vm_pop(); struct us_val a = vm_pop(); if (b.type != VAL_NUM || a.type != VAL_NUM) - log_fatal(1, "Invalid operands"); + us_err("Invalid operands"); vm_push(create_bool(get_num(a) <= get_num(b))); break; } case BC_NEG: { struct us_val a = vm_pop(); if (a.type != VAL_NUM) - log_fatal(1, "Invalid operand"); + us_err("Invalid operand"); vm_push(create_num(-get_num(a))); break; } @@ -436,7 +459,7 @@ void us_exec(struct us_func *func) return; } default: - log_fatal(1, "unhandled instruction %d", instruction); + us_err("unhandled instruction %d", instruction); break; } } |
