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)
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);
+ }
+}
#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
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));
--- /dev/null
+#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
-#ifndef _ERR_H_
-#define _ERR_H_
+#ifndef _COMMON_ERR_H_
+#define _COMMON_ERR_H_
#include <stdio.h>
#include <stdlib.h>
exit(1);
}
+static inline void syserror(const char *call, FILE *file)
+{
+ perror(call);
+
+ if (file)
+ fclose(file);
+
+ exit(1);
+}
+
#endif
--- /dev/null
+#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
-#ifndef _UTIL_H_
-#define _UTIL_H_
+#ifndef _COMMON_STR_H_
+#define _COMMON_STR_H_
#include <stdio.h>
#include <stdarg.h>
#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"
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
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;
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;
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;
*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);
}
}
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);
break;
if (ferror(f))
- error("%s: I/O error\n", filename);
+ syserror("getc", f);
if (c == '\n')
++lines;
#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);
#include <stdlib.h>
#include <stdio.h>
#include "common/err.h"
+#include "common/dl.h"
#include "load.h"
#include "run.h"
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];
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)
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))
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))
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);
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);
}
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);
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);
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);
}
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();
}
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);