From: Elias Fleckenstein Date: Thu, 30 Dec 2021 20:53:01 +0000 (+0100) Subject: Unify error messages and checking X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=dd3da75c8d9da1f589ac6dded6140a4dc8d4b93f;p=uwu-lang.git Unify error messages and checking --- diff --git a/api/util.c b/api/util.c index e6f0650..b6f9b49 100644 --- a/api/util.c +++ b/api/util.c @@ -4,8 +4,7 @@ UwUVMValue uwuutil_is_type(const char *fnname, UwUVMArgs *args, UwUVMType *type) { - if (args->num < 1) - error("error: %s requires at least one argument\n", fnname); + uwuutil_require_min(fnname, args, 1); for (size_t i = 0; i < args->num; i++) if (uwuvm_get_arg(args, i).type != type) @@ -13,3 +12,35 @@ UwUVMValue uwuutil_is_type(const char *fnname, UwUVMArgs *args, UwUVMType *type) return uwubool_create(true); } + +void uwuutil_require_min(const char *fnname, UwUVMArgs *args, size_t n) +{ + if (args->num < n) { + if (n == 1) + error("type error: %s requires at least one optional argument, but none were given\n", fnname); + else + error("type error: %s requires at least %d arguments, but only %d were given\n", fnname, n, args->num); + } +} + +void uwuutil_require_max(const char *fnname, UwUVMArgs *args, size_t n) +{ + if (args->num > n) { + if (n == 1) + error("type error: %s accepts one optional argument, but %d were given\n", fnname, args->num); + else + error("type error: %s does not take more than %d arguments, but %d were given\n", fnname, args->num); + } +} + +void uwuutil_require_exact(const char *fnname, UwUVMArgs *args, size_t n) +{ + if (args->num != n) { + if (n == 0) + error("type error: %s does not take any arguments, but %d were given\n", fnname, args->num); + else if (n == 1) + error("type error: %s requires exactly one argument, but %d were given\n", fnname, args->num); + else + error("type error: %s requires exactly %d arguments, but %d were given\n", fnname, n, args->num); + } +} diff --git a/api/util.h b/api/util.h index 259f53a..d594107 100644 --- a/api/util.h +++ b/api/util.h @@ -4,5 +4,9 @@ #include "vm.h" UwUVMValue uwuutil_is_type(const char *fnname, UwUVMArgs *args, UwUVMType *type); +void uwuutil_require_min (const char *fnname, UwUVMArgs *args, size_t n); +void uwuutil_require_max (const char *fnname, UwUVMArgs *args, size_t n); +void uwuutil_require_exact(const char *fnname, UwUVMArgs *args, size_t n); +void uwuutil_require_none (const char *fnname, UwUVMArgs *args); #endif diff --git a/api/vm.c b/api/vm.c index 8374050..52a003c 100644 --- a/api/vm.c +++ b/api/vm.c @@ -45,7 +45,7 @@ UwUVMValue uwuvm_evaluate_expression(UwUVMExpression *expression, UwUVMArgs *arg case EX_ARGNUM: if ((size_t) expression->value.int_value >= args->num) - error("error: not enough arguments (accessed argument $%d, but only %lu arguments were passed)\n", expression->value.int_value, args->num); + error("type error: not enough arguments (accessed argument $%d, but only %lu arguments were passed)\n", expression->value.int_value, args->num); return uwuvm_clone_value(uwuvm_get_arg(args, expression->value.int_value)); diff --git a/common/err.h b/common/err.h index 34620bb..b9faf11 100644 --- a/common/err.h +++ b/common/err.h @@ -14,4 +14,14 @@ static inline void error(const char *format, ...) exit(1); } +static inline void syserror(const char *call, FILE *file) +{ + perror(call); + + if (file) + fclose(file); + + exit(1); +} + #endif diff --git a/common/perr.h b/common/perr.h new file mode 100644 index 0000000..ffd0f5d --- /dev/null +++ b/common/perr.h @@ -0,0 +1,8 @@ +#ifndef _COMMON_PERR_H_ +#define _COMMON_PERR_H_ + + + + + +#endif diff --git a/src/load.c b/src/load.c index aeee1c2..f6386d6 100644 --- a/src/load.c +++ b/src/load.c @@ -112,7 +112,7 @@ static Module *require_module(LoadState *state, char *module_path) char *filename = get_filename(module_path); if (! filename) - error("error: module %s not found\n", module_path); + error("module error: module %s not found\n", module_path); size_t filename_len = strlen(filename); UwUVMModuleType type = (filename_len >= 3 && strcmp(filename + filename_len - 3, ".so") == 0) ? MODULE_NATIVE : MODULE_PLAIN; @@ -180,7 +180,7 @@ static UwUVMFunction *resolve_function(LoadState *state, Module *caller_module, fnname++; if (*fnname == '\0') - error("error: empty function name\n"); + error("module error: empty function name referenced/called by module %s\n", caller_module->filename); Module *callee_module; @@ -275,7 +275,7 @@ static void load_functions(LoadState *state, Module *module) *function = NULL; } else { - error("error: no function %s in module %s\n", link->name, module->filename); + error("module error: no function %s in module %s\n", link->name, module->filename); } } else { char *symbol = asprintf_wrapper("uwu_%s", link->name); diff --git a/src/parse.c b/src/parse.c index ed09de9..e8f1d38 100644 --- a/src/parse.c +++ b/src/parse.c @@ -285,7 +285,7 @@ AbstractSyntaxTree parse_file(const char *filename) FILE *f = fopen(filename, "r"); if (! f) - error("%s: unable to open\n", filename); + syserror("fopen", f); #if DEBUG printf("[File %s]\n[Line %d]\n", filename, lines); @@ -298,7 +298,7 @@ AbstractSyntaxTree parse_file(const char *filename) break; if (ferror(f)) - error("%s: I/O error\n", filename); + syserror("getc", f); if (c == '\n') ++lines; @@ -309,11 +309,11 @@ AbstractSyntaxTree parse_file(const char *filename) #endif if (! parse_character(&state, c)) - error("%s: syntax error in line %d\n", filename, lines); + error("syntax error: in file %s, line %d\n", filename, lines); } if (state.buffer || state.expression) - error("%s: syntax error at end of file\n", filename); + error("syntax error: at end of file %s\n", filename); fclose(f); diff --git a/std/bool.c b/std/bool.c index 349e1c9..8c8df7d 100644 --- a/std/bool.c +++ b/std/bool.c @@ -12,8 +12,7 @@ static inline bool get_bool_arg(UwUVMArgs *args, size_t i) UwUVMValue uwu_if(UwUVMArgs *args) { - if (args->num != 3) - error("error: :bool:if requires exactly 3 arguments\n"); + uwuutil_require_exact(":bool:if", args, 3); return uwuvm_clone_value(get_bool_arg(args, 0) ? uwuvm_get_arg(args, 1) @@ -23,8 +22,7 @@ UwUVMValue uwu_if(UwUVMArgs *args) UwUVMValue uwu_and(UwUVMArgs *args) { - if (args->num < 1) - error("error: :bool:and requires at least one argument\n"); + uwuutil_require_min(":bool:and", args, 1); for (size_t i = 0; i < args->num; i++) if (! get_bool_arg(args, i)) @@ -35,8 +33,7 @@ UwUVMValue uwu_and(UwUVMArgs *args) UwUVMValue uwu_or(UwUVMArgs *args) { - if (args->num < 1) - error("error: :bool:or requires at least one argument\n"); + uwuutil_require_min(":bool:or", args, 1); for (size_t i = 0; i < args->num; i++) if (get_bool_arg(args, i)) @@ -47,8 +44,7 @@ UwUVMValue uwu_or(UwUVMArgs *args) UwUVMValue uwu_equal(UwUVMArgs *args) { - if (args->num < 2) - error("error: :bool:equal requires at least 2 arguments\n"); + uwuutil_require_min(":bool:equal", args, 2); bool value = get_bool_arg(args, 0); @@ -61,25 +57,19 @@ UwUVMValue uwu_equal(UwUVMArgs *args) UwUVMValue uwu_not(UwUVMArgs *args) { - if (args->num != 1) - error("error: :bool:not requires exactly 1 argument\n"); - + uwuutil_require_exact(":bool:not", args, 1); return uwubool_create(! get_bool_arg(args, 0)); } UwUVMValue uwu_true(UwUVMArgs *args) { - if (args->num != 0) - error("error: :bool:true does not take any arguments\n"); - + uwuutil_require_exact(":bool:true", args, 0); return uwubool_create(true); } UwUVMValue uwu_false(UwUVMArgs *args) { - if (args->num != 0) - error("error: :bool:false does not take any arguments\n"); - + uwuutil_require_exact(":bool:false", args, 0); return uwubool_create(false); } diff --git a/std/int.c b/std/int.c index 22af320..300737b 100644 --- a/std/int.c +++ b/std/int.c @@ -18,18 +18,17 @@ typedef enum static int binary(const char *fnname, UwUVMArgs *args, BinaryOP op) { - if (args->num != 2) - error("error: %s requires exactly 2 arguments\n", fnname); + uwuutil_require_exact(fnname, args, 2); UwUVMValue value0 = uwuvm_get_arg(args, 0); if (value0.type != &uwuint_type) - error("error: %s requires an integer as $0\n", fnname); + error("type error: %s requires an integer as $0\n", fnname); UwUVMValue value1 = uwuvm_get_arg(args, 1); if (value1.type != &uwuint_type) - error("error: %s requires an integer as $1\n", fnname); + error("type error: %s requires an integer as $1\n", fnname); int a = uwuint_get(value0); int b = uwuint_get(value1); @@ -59,7 +58,7 @@ static int reduce(const char *fnname, UwUVMArgs *args, ReduceOP op, int result) UwUVMValue value = uwuvm_get_arg(args, i); if (value.type != &uwuint_type) - error("error: %s only accepts integers as arguments (invalid argument: $%lu)\n", fnname, i); + error("type error: %s only accepts integers as arguments (invalid argument: $%lu)\n", fnname, i); int this = uwuint_get(value); @@ -116,9 +115,7 @@ UwUVMValue uwu_greater(UwUVMArgs *args) UwUVMValue uwu_equal(UwUVMArgs *args) { - if (args->num < 2) - error("error: :int:equal requires at least 2 arguments\n"); - + uwuutil_require_min(":int:equal", args, 2); return uwubool_create(reduce(":int:equal", args, ROP_EQU, 1) == 1); } diff --git a/std/nil.c b/std/nil.c index 93172eb..52a2872 100644 --- a/std/nil.c +++ b/std/nil.c @@ -4,9 +4,7 @@ UwUVMValue uwu_nil(UwUVMArgs *args) { - if (args->num != 0) - error(":nil:nil does not accept any arguments\n"); - + uwuutil_require_exact(":nil:nil", args, 0); return uwunil_create(); } diff --git a/std/ref.c b/std/ref.c index 62c0a52..f92e4b0 100644 --- a/std/ref.c +++ b/std/ref.c @@ -4,8 +4,7 @@ UwUVMValue uwu_call(UwUVMArgs *args) { - if (args->num < 1) - error(":ref:call requires at least one argument\n"); + uwuutil_require_min(":ref:call", args, 1); UwUVMValue value = uwuvm_get_arg(args, 0);