diff options
-rw-r--r-- | api/util.c | 35 | ||||
-rw-r--r-- | api/util.h | 4 | ||||
-rw-r--r-- | api/vm.c | 2 | ||||
-rw-r--r-- | common/dl.h | 14 | ||||
-rw-r--r-- | common/err.h | 14 | ||||
-rw-r--r-- | common/file.h | 19 | ||||
-rw-r--r-- | common/str.h | 4 | ||||
-rw-r--r-- | src/load.c | 29 | ||||
-rw-r--r-- | src/parse.c | 8 | ||||
-rw-r--r-- | src/run.c | 5 | ||||
-rw-r--r-- | std/bool.c | 24 | ||||
-rw-r--r-- | std/int.c | 13 | ||||
-rw-r--r-- | std/nil.c | 4 | ||||
-rw-r--r-- | std/ref.c | 3 |
14 files changed, 112 insertions, 66 deletions
@@ -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); + } +} @@ -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 @@ -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/dl.h b/common/dl.h new file mode 100644 index 0000000..143b422 --- /dev/null +++ b/common/dl.h @@ -0,0 +1,14 @@ +#ifndef _COMMON_DL_H_ +#define _COMMON_DL_H_ + +#include <dlfcn.h> +#include "err.h" + +inline static void check_dlerror() +{ + char *err = dlerror(); + if (err) + error("library error: %s\n", err); +} + +#endif diff --git a/common/err.h b/common/err.h index 1dccbf9..b9faf11 100644 --- a/common/err.h +++ b/common/err.h @@ -1,5 +1,5 @@ -#ifndef _ERR_H_ -#define _ERR_H_ +#ifndef _COMMON_ERR_H_ +#define _COMMON_ERR_H_ #include <stdio.h> #include <stdlib.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/file.h b/common/file.h new file mode 100644 index 0000000..c5e8036 --- /dev/null +++ b/common/file.h @@ -0,0 +1,19 @@ +#ifndef _COMMON_FILE_H_ +#define _COMMON_FILE_H_ + +#include <stdio.h> +#include <stdbool.h> + +inline static bool file_exists(const char *filename) +{ + FILE *f = fopen(filename, "r"); + + if (f) { + fclose(f); + return true; + } + + return false; +} + +#endif diff --git a/common/str.h b/common/str.h index b0baa37..fc5f587 100644 --- a/common/str.h +++ b/common/str.h @@ -1,5 +1,5 @@ -#ifndef _UTIL_H_ -#define _UTIL_H_ +#ifndef _COMMON_STR_H_ +#define _COMMON_STR_H_ #include <stdio.h> #include <stdarg.h> @@ -6,6 +6,8 @@ #include <dlfcn.h> #include "common/err.h" #include "common/str.h" +#include "common/file.h" +#include "common/dl.h" #include "load.h" #include "parse.h" @@ -33,18 +35,6 @@ static char *dirname_wrapper(const char *name) return wrap_name_func(name, &dirname); } -static bool file_exists(const char *filename) -{ - FILE *f = fopen(filename, "r"); - - if (f) { - fclose(f); - return true; - } - - return false; -} - // type definitions typedef struct @@ -122,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; @@ -148,9 +138,7 @@ static Module *require_module(LoadState *state, char *module_path) state->program.libraries = realloc(state->program.libraries, sizeof(void *) * ++state->program.num_libraries); state->program.libraries[state->program.num_libraries - 1] = module->handle.lib = dlopen(filename, RTLD_LAZY); - char *err = dlerror(); - if (err) - error("library error: %s\n", err); + check_dlerror(); } return module; @@ -192,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; @@ -287,16 +275,13 @@ 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); link->ref->value.native = dlsym(module->handle.lib, symbol); - char *err = dlerror(); - if (err) - error("library error: %s\n", err); - + check_dlerror(); free(symbol); } } 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); @@ -2,6 +2,7 @@ #include <stdlib.h> #include <stdio.h> #include "common/err.h" +#include "common/dl.h" #include "load.h" #include "run.h" @@ -29,9 +30,7 @@ void run_module(const char *progname, const char *modname, size_t num_args, char char *(*uwuvm_print_value )(UwUVMValue ) = dlsym(program.api_library, "uwuvm_print_value" ); void (*uwuvm_delet_value )(UwUVMValue ) = dlsym(program.api_library, "uwuvm_delet_value" ); - char *err = dlerror(); - if (err) - error("library error: %s\n", err); + check_dlerror(); UwUVMExpression arg_expressions[num_args]; @@ -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); } @@ -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); } @@ -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(); } @@ -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); |