From: Elias Fleckenstein Date: Thu, 30 Dec 2021 17:31:53 +0000 (+0100) Subject: Allow passing arguments to program, refactor directory structure X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=ec14f2955222932bb68704cc4590ba1dbd165cd9;p=uwu-lang.git Allow passing arguments to program, refactor directory structure --- diff --git a/Makefile b/Makefile index 17c6922..da9c509 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: uwu std api uwu: src/*.c src/*.h - gcc -g src/*.c -o uwu -ldl -D_GNU_SOURCE + gcc -g -I. src/*.c -o uwu -D_GNU_SOURCE -ldl .PHONY: std api @@ -9,10 +9,10 @@ std: std/bool.so std/int.so std/str.so std/nil.so std/ref.so api: api/api.so std/%.so: std/%.c - gcc -g -shared -fpic $< -o $@ -D_GNU_SOURCE + gcc -g -I. -shared -fpic $< -o $@ -D_GNU_SOURCE api/api.so: api/*.c api/*.h - gcc -g -shared -fpic api/*.c -o api/api.so -D_GNU_SOURCE + gcc -g -I. -shared -fpic api/*.c -o api/api.so -D_GNU_SOURCE .PHONY: clean diff --git a/README.md b/README.md index 211c407..c762b4a 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ make To run: ``` -./uwu +./uwu ``` `` is a path relative to the current directory. diff --git a/api/int.c b/api/int.c index 8446d1d..b1e0c69 100644 --- a/api/int.c +++ b/api/int.c @@ -1,5 +1,5 @@ #include -#include "../src/util.h" +#include "common/str.h" #include "int.h" UwUVMValue uwuint_create(int value) diff --git a/api/ref.c b/api/ref.c index 43eb68e..517869e 100644 --- a/api/ref.c +++ b/api/ref.c @@ -1,4 +1,4 @@ -#include "../src/util.h" +#include "common/str.h" #include "ref.h" UwUVMValue uwuref_create(UwUVMFunction *value) diff --git a/api/util.c b/api/util.c index c3e8a38..e6f0650 100644 --- a/api/util.c +++ b/api/util.c @@ -1,4 +1,4 @@ -#include "../src/err.h" +#include "common/err.h" #include "util.h" #include "bool.h" diff --git a/api/vm.c b/api/vm.c index 5cab6c0..8374050 100644 --- a/api/vm.c +++ b/api/vm.c @@ -1,6 +1,6 @@ #include #include -#include "../src/err.h" +#include "common/err.h" #include "vm.h" #include "str.h" #include "ref.h" diff --git a/api/vm.h b/api/vm.h index 81465f8..fc761d3 100644 --- a/api/vm.h +++ b/api/vm.h @@ -3,7 +3,6 @@ #include #include -#include "../src/expression.h" typedef enum { @@ -11,6 +10,16 @@ typedef enum MODULE_NATIVE, } UwUVMModuleType; +typedef enum +{ + EX_UNINIT, + EX_INTLIT, + EX_STRLIT, + EX_ARGNUM, + EX_FNNAME, + EX_FNCALL, +} UwUVMExpressionType; + typedef struct { void *(*clone)(void *data); @@ -46,7 +55,7 @@ typedef struct typedef struct UwUVMExpression { - ExpressionType type; + UwUVMExpressionType type; union { struct @@ -61,16 +70,6 @@ typedef struct UwUVMExpression } value; } UwUVMExpression; -typedef struct -{ - void *api_library; - UwUVMFunction *main_function; - UwUVMFunction **functions; - size_t num_functions; - void **libraries; - size_t num_libraries; -} UwUVMProgram; - UwUVMValue uwuvm_clone_value(UwUVMValue value); void uwuvm_delet_value(UwUVMValue value); char *uwuvm_print_value(UwUVMValue value); diff --git a/common/err.h b/common/err.h new file mode 100644 index 0000000..1dccbf9 --- /dev/null +++ b/common/err.h @@ -0,0 +1,17 @@ +#ifndef _ERR_H_ +#define _ERR_H_ + +#include +#include +#include + +static inline void error(const char *format, ...) +{ + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + exit(1); +} + +#endif diff --git a/common/str.h b/common/str.h new file mode 100644 index 0000000..b0baa37 --- /dev/null +++ b/common/str.h @@ -0,0 +1,17 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include +#include + +static inline char *asprintf_wrapper(const char *format, ...) +{ + va_list args; + va_start(args, format); + char *ptr; + vasprintf(&ptr, format, args); + va_end(args); + return ptr; +} + +#endif diff --git a/example/print_args.uwu b/example/print_args.uwu new file mode 100644 index 0000000..2256a88 --- /dev/null +++ b/example/print_args.uwu @@ -0,0 +1,5 @@ +main :str:cat( + $0, + $1, + $2 +) diff --git a/src/collect.c b/src/collect.c deleted file mode 100644 index ae15513..0000000 --- a/src/collect.c +++ /dev/null @@ -1,406 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "err.h" -#include "util.h" -#include "collect.h" -#include "parse.h" - -#define DEBUG 0 - -// helper functions - -static char *wrap_name_func(const char *name, char *(*fn)(char *)) -{ - char *copy = strdup(name); - char *result = fn(copy); - char *result_copy = strdup(result); - - free(copy); - return result_copy; -} - -static char *basename_wrapper(const char *name) -{ - return wrap_name_func(name, &basename); -} - -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 -{ - char *name; - UwUVMFunction *ref; -} FunctionLink; - -typedef struct -{ - char *path; // path without file extension - char *filename; // path with file extension - char *environment; // directory path - - UwUVMModuleType type; // native (.so) or plain (.uwu) - - FunctionLink *functions; // required functions - size_t num_functions; // number of required functions - size_t loaded_functions; // number of loaded functions (<= num_functions) - - union - { - AbstractSyntaxTree ast; // abstract syntax tree generated by parser (for plain modules) - void *lib; // dlopen() shared object handle (for native modules) - } handle; -} Module; - -typedef struct -{ - Module **modules; // loaded modules - size_t num_modules; // count for modules - - char *std_path; // path to standard library - - UwUVMProgram program; // the result program -} CollectorState; - -// functions - -// returns mallocated string -static inline char *get_filename(const char *module_path) -{ - const char *try_names[3] = { - "%s", - "%s.uwu", - "%s.so", - }; - - char *filename; - - for (int i = 0; i < 3; i++) { - filename = asprintf_wrapper(try_names[i], module_path); - - if (file_exists(filename)) - return filename; - else - free(filename); - } - - return NULL; -} - -// module_path is a mallocated string -static Module *require_module(CollectorState *state, char *module_path) -{ - for (size_t i = 0; i < state->num_modules; i++) { - Module *module = state->modules[i]; - - if (strcmp(module_path, module->path) == 0) { - free(module_path); - return module; - } - } - - char *filename = get_filename(module_path); - - if (! filename) - error("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->modules = realloc(state->modules, sizeof *state->modules * ++state->num_modules); - Module *module = state->modules[state->num_modules - 1] = malloc(sizeof *module); - - *module = (Module) { - .path = module_path, - .filename = filename, - .environment = dirname_wrapper(module_path), - - .type = type, - - .functions = NULL, - .num_functions = 0, - .loaded_functions = 0, - }; - - if (type == MODULE_PLAIN) { - module->handle.ast = parse_file(filename); - } else { - 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("%s\n", err); - } - - return module; -} - -static UwUVMFunction *require_function(CollectorState *state, Module *module, const char *name) -{ - for (size_t i = 0; i < module->num_functions; i++) { - FunctionLink *link = &module->functions[i]; - - if (strcmp(link->name, name) == 0) - return link->ref; - } - - UwUVMFunction *ref = malloc(sizeof *ref); - ref->type = module->type; - - state->program.functions = realloc(state->program.functions, sizeof *state->program.functions * ++state->program.num_functions); - state->program.functions[state->program.num_functions - 1] = ref; - - module->functions = realloc(module->functions, sizeof *module->functions * ++module->num_functions); - module->functions[module->num_functions - 1] = (FunctionLink) { - .name = strdup(name), - .ref = ref, - }; - - return ref; -} - -static UwUVMFunction *resolve_function(CollectorState *state, Module *caller_module, const char *full_name) -{ - size_t len = strlen(full_name); - - const char *fnname; - for (fnname = &full_name[len - 1]; *fnname != ':' && fnname > full_name; fnname--) - ; - - if (*fnname == ':') - fnname++; - - if (*fnname == '\0') - error("error: empty function name\n"); - - Module *callee_module; - - if (fnname == full_name) { - callee_module = caller_module; - } else { - const char *caller_path = caller_module->environment; - const char *callee_name = full_name; - - if (*callee_name == ':') { - caller_path = state->std_path; - callee_name++; - } - - size_t path_len = fnname - callee_name; - char callee_path[path_len]; - - for (size_t i = 0; i < path_len; i++) - callee_path[i] = (i == path_len - 1) ? '\0' - : (callee_name[i] == ':') ? '/' - : callee_name[i]; - - callee_module = require_module(state, asprintf_wrapper("%s/%s", caller_path, callee_path)); - } - - return require_function(state, callee_module, fnname); -} - -static void translate_expression(CollectorState *state, Module *module, UwUVMExpression *vm_expr, ParseExpression *parse_expr) -{ - UwUVMFunction *vm_function; - - if (parse_expr->type == EX_FNNAME || parse_expr->type == EX_FNCALL) { - vm_function = resolve_function(state, module, parse_expr->value.str_value); - free(parse_expr->value.str_value); - } - - switch (vm_expr->type = parse_expr->type) { - case EX_INTLIT: - case EX_ARGNUM: - vm_expr->value.int_value = parse_expr->value.int_value; - break; - - case EX_STRLIT: - vm_expr->value.str_value = parse_expr->value.str_value; - break; - - case EX_FNNAME: - vm_expr->value.ref_value = vm_function; - break; - - case EX_FNCALL: - vm_expr->value.cll_value.function = vm_function; - vm_expr->value.cll_value.args = malloc(sizeof(UwUVMExpression) * parse_expr->num_children); - vm_expr->value.cll_value.num_args = parse_expr->num_children; - - for (size_t i = 0; i < parse_expr->num_children; i++) - translate_expression(state, module, &vm_expr->value.cll_value.args[i], parse_expr->children[i]); - - if (parse_expr->children) - free(parse_expr->children); - break; - - default: - break; - } - - free(parse_expr); -} - -static void load_functions(CollectorState *state, Module *module) -{ - for (; module->loaded_functions < module->num_functions; module->loaded_functions++) { - FunctionLink *linkptr = &module->functions[module->loaded_functions]; - FunctionLink link = *linkptr; - - bool found = false; - - if (module->type == MODULE_PLAIN) { - ParseFunction **function = NULL; - - for (size_t i = 0; i < module->handle.ast.num_functions; i++) { - ParseFunction **fn = &module->handle.ast.functions[i]; - - if (*fn && strcmp((*fn)->name, link.name) == 0) { - function = fn; - break; - } - } - - if (function) { - found = true; - linkptr = NULL; - - translate_expression(state, module, link.ref->value.plain = malloc(sizeof(UwUVMExpression)), (*function)->expression); - free((*function)->name); - free(*function); - - *function = NULL; - } - } else { - char *symbol = asprintf_wrapper("uwu_%s", link.name); - linkptr->ref->value.native = dlsym(module->handle.lib, symbol); - - if (! dlerror()) - found = true; - - free(symbol); - } - - if (! found) - error("error: no function %s in module %s\n", link.name, module->filename); - } -} - -static void free_expression(ParseExpression *expr) -{ - if (expr->type == EX_FNCALL) { - for (size_t i = 0; i < expr->num_children; i++) - free_expression(expr->children[i]); - - if (expr->children) - free(expr->children); - } - - if (expr->type != EX_INTLIT && expr->type != EX_ARGNUM) - free(expr->value.str_value); - - free(expr); -} - -UwUVMProgram create_program(const char *progname, const char *modname) -{ - char *prog_dirname = dirname_wrapper(progname); - char *api_path = asprintf_wrapper("%s/api/api.so", prog_dirname); - - CollectorState state = { - .modules = NULL, - .num_modules = 0, - .std_path = asprintf_wrapper("%s/std", prog_dirname), - .program = { - .api_library = dlopen(api_path, RTLD_NOW | RTLD_GLOBAL), - .main_function = NULL, - .functions = NULL, - .num_functions = 0, - .libraries = NULL, - .num_libraries = 0, - }, - }; - - free(prog_dirname); - free(api_path); - - state.program.main_function = require_function(&state, require_module(&state, strdup(modname)), "main"); - - while (true) { - bool fully_loaded = true; - - for (size_t i = 0; i < state.num_modules; i++) { - Module *module = state.modules[i]; - -#if DEBUG - printf("%s %lu/%lu\n", module->filename, module->loaded_functions, module->num_functions); -#endif - - if (module->loaded_functions < module->num_functions) { - fully_loaded = false; - load_functions(&state, module); - } - } - - if (fully_loaded) - break; - } - - free(state.std_path); - - for (size_t i = 0; i < state.num_modules; i++) { - Module *module = state.modules[i]; - - free(module->path); - free(module->filename); - free(module->environment); - - for (size_t f = 0; f < module->num_functions; f++) - free(module->functions[f].name); - - free(module->functions); - - if (module->type == MODULE_PLAIN) { - for (size_t f = 0; f < module->handle.ast.num_functions; f++) { - ParseFunction *function = module->handle.ast.functions[f]; - - if (function) { - free_expression(function->expression); - free(function->name); - free(function); - } - } - - if (module->handle.ast.functions) - free(module->handle.ast.functions); - } - - free(module); - } - - free(state.modules); - - return state.program; -} diff --git a/src/collect.h b/src/collect.h deleted file mode 100644 index da118a5..0000000 --- a/src/collect.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _COLLECT_H_ -#define _COLLECT_H_ - -#include "../api/vm.h" - -UwUVMProgram create_program(const char *progname, const char *modname); - -#endif diff --git a/src/err.h b/src/err.h deleted file mode 100644 index 1dccbf9..0000000 --- a/src/err.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ERR_H_ -#define _ERR_H_ - -#include -#include -#include - -static inline void error(const char *format, ...) -{ - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - exit(1); -} - -#endif diff --git a/src/expression.h b/src/expression.h deleted file mode 100644 index 55d10f7..0000000 --- a/src/expression.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _EXPRESSION_H_ -#define _EXPRESSION_H_ - -typedef enum -{ - EX_UNINIT, - EX_INTLIT, - EX_STRLIT, - EX_ARGNUM, - EX_FNNAME, - EX_FNCALL, -} ExpressionType; - -#endif diff --git a/src/load.c b/src/load.c new file mode 100644 index 0000000..edeba97 --- /dev/null +++ b/src/load.c @@ -0,0 +1,400 @@ +#include +#include +#include +#include +#include +#include +#include "common/err.h" +#include "common/str.h" +#include "load.h" +#include "parse.h" + +#define DEBUG 0 + +// helper functions + +static char *wrap_name_func(const char *name, char *(*fn)(char *)) +{ + char *copy = strdup(name); + char *result = fn(copy); + char *result_copy = strdup(result); + + free(copy); + return result_copy; +} + +static char *basename_wrapper(const char *name) +{ + return wrap_name_func(name, &basename); +} + +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 +{ + char *name; + UwUVMFunction *ref; +} FunctionLink; + +typedef struct +{ + char *path; // path without file extension + char *filename; // path with file extension + char *environment; // directory path + + UwUVMModuleType type; // native (.so) or plain (.uwu) + + FunctionLink *functions; // required functions + size_t num_functions; // number of required functions + size_t loaded_functions; // number of loaded functions (<= num_functions) + + union + { + AbstractSyntaxTree ast; // abstract syntax tree generated by parser (for plain modules) + void *lib; // dlopen() shared object handle (for native modules) + } handle; +} Module; + +typedef struct +{ + Module **modules; // loaded modules + size_t num_modules; // count for modules + + char *std_path; // path to standard library + + Program program; // the result program +} LoadState; + +// functions + +// returns mallocated string +static inline char *get_filename(const char *module_path) +{ + const char *try_names[3] = { + "%s", + "%s.uwu", + "%s.so", + }; + + char *filename; + + for (int i = 0; i < 3; i++) { + filename = asprintf_wrapper(try_names[i], module_path); + + if (file_exists(filename)) + return filename; + else + free(filename); + } + + return NULL; +} + +// module_path is a mallocated string +static Module *require_module(LoadState *state, char *module_path) +{ + for (size_t i = 0; i < state->num_modules; i++) { + Module *module = state->modules[i]; + + if (strcmp(module_path, module->path) == 0) { + free(module_path); + return module; + } + } + + char *filename = get_filename(module_path); + + if (! filename) + error("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->modules = realloc(state->modules, sizeof *state->modules * ++state->num_modules); + Module *module = state->modules[state->num_modules - 1] = malloc(sizeof *module); + + *module = (Module) { + .path = module_path, + .filename = filename, + .environment = dirname_wrapper(module_path), + + .type = type, + + .functions = NULL, + .num_functions = 0, + .loaded_functions = 0, + }; + + if (type == MODULE_PLAIN) { + module->handle.ast = parse_file(filename); + } else { + 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); + } + + return module; +} + +static UwUVMFunction *require_function(LoadState *state, Module *module, const char *name) +{ + for (size_t i = 0; i < module->num_functions; i++) { + FunctionLink *link = &module->functions[i]; + + if (strcmp(link->name, name) == 0) + return link->ref; + } + + UwUVMFunction *ref = malloc(sizeof *ref); + ref->type = module->type; + + state->program.functions = realloc(state->program.functions, sizeof *state->program.functions * ++state->program.num_functions); + state->program.functions[state->program.num_functions - 1] = ref; + + module->functions = realloc(module->functions, sizeof *module->functions * ++module->num_functions); + module->functions[module->num_functions - 1] = (FunctionLink) { + .name = strdup(name), + .ref = ref, + }; + + return ref; +} + +static UwUVMFunction *resolve_function(LoadState *state, Module *caller_module, const char *full_name) +{ + size_t len = strlen(full_name); + + const char *fnname; + for (fnname = &full_name[len - 1]; *fnname != ':' && fnname > full_name; fnname--) + ; + + if (*fnname == ':') + fnname++; + + if (*fnname == '\0') + error("error: empty function name\n"); + + Module *callee_module; + + if (fnname == full_name) { + callee_module = caller_module; + } else { + const char *caller_path = caller_module->environment; + const char *callee_name = full_name; + + if (*callee_name == ':') { + caller_path = state->std_path; + callee_name++; + } + + size_t path_len = fnname - callee_name; + char callee_path[path_len]; + + for (size_t i = 0; i < path_len; i++) + callee_path[i] = (i == path_len - 1) ? '\0' + : (callee_name[i] == ':') ? '/' + : callee_name[i]; + + callee_module = require_module(state, asprintf_wrapper("%s/%s", caller_path, callee_path)); + } + + return require_function(state, callee_module, fnname); +} + +static void translate_expression(LoadState *state, Module *module, UwUVMExpression *vm_expr, ParseExpression *parse_expr) +{ + UwUVMFunction *vm_function; + + if (parse_expr->type == EX_FNNAME || parse_expr->type == EX_FNCALL) { + vm_function = resolve_function(state, module, parse_expr->value.str_value); + free(parse_expr->value.str_value); + } + + switch (vm_expr->type = parse_expr->type) { + case EX_INTLIT: + case EX_ARGNUM: + vm_expr->value.int_value = parse_expr->value.int_value; + break; + + case EX_STRLIT: + vm_expr->value.str_value = parse_expr->value.str_value; + break; + + case EX_FNNAME: + vm_expr->value.ref_value = vm_function; + break; + + case EX_FNCALL: + vm_expr->value.cll_value.function = vm_function; + vm_expr->value.cll_value.args = malloc(sizeof(UwUVMExpression) * parse_expr->num_children); + vm_expr->value.cll_value.num_args = parse_expr->num_children; + + for (size_t i = 0; i < parse_expr->num_children; i++) + translate_expression(state, module, &vm_expr->value.cll_value.args[i], parse_expr->children[i]); + + if (parse_expr->children) + free(parse_expr->children); + break; + + default: + break; + } + + free(parse_expr); +} + +static void load_functions(LoadState *state, Module *module) +{ + for (; module->loaded_functions < module->num_functions; module->loaded_functions++) { + FunctionLink *link = &module->functions[module->loaded_functions]; + + if (module->type == MODULE_PLAIN) { + ParseFunction **function = NULL; + + for (size_t i = 0; i < module->handle.ast.num_functions; i++) { + ParseFunction **fn = &module->handle.ast.functions[i]; + + if (*fn && strcmp((*fn)->name, link->name) == 0) { + function = fn; + break; + } + } + + if (function) { + translate_expression(state, module, link->ref->value.plain = malloc(sizeof(UwUVMExpression)), (*function)->expression); + free((*function)->name); + free(*function); + + *function = NULL; + } else { + error("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); + + free(symbol); + } + } +} + +static void free_expression(ParseExpression *expr) +{ + if (expr->type == EX_FNCALL) { + for (size_t i = 0; i < expr->num_children; i++) + free_expression(expr->children[i]); + + if (expr->children) + free(expr->children); + } + + if (expr->type != EX_INTLIT && expr->type != EX_ARGNUM) + free(expr->value.str_value); + + free(expr); +} + +Program load_program(const char *progname, const char *modname) +{ + char *prog_dirname = dirname_wrapper(progname); + char *api_path = asprintf_wrapper("%s/api/api.so", prog_dirname); + + LoadState state = { + .modules = NULL, + .num_modules = 0, + .std_path = asprintf_wrapper("%s/std", prog_dirname), + .program = { + .api_library = dlopen(api_path, RTLD_NOW | RTLD_GLOBAL), + .main_function = NULL, + .functions = NULL, + .num_functions = 0, + .libraries = NULL, + .num_libraries = 0, + }, + }; + + free(prog_dirname); + free(api_path); + + state.program.main_function = require_function(&state, require_module(&state, strdup(modname)), "main"); + + while (true) { + bool fully_loaded = true; + + for (size_t i = 0; i < state.num_modules; i++) { + Module *module = state.modules[i]; + +#if DEBUG + printf("%s %lu/%lu\n", module->filename, module->loaded_functions, module->num_functions); +#endif + + if (module->loaded_functions < module->num_functions) { + fully_loaded = false; + load_functions(&state, module); + } + } + + if (fully_loaded) + break; + } + + free(state.std_path); + + for (size_t i = 0; i < state.num_modules; i++) { + Module *module = state.modules[i]; + + free(module->path); + free(module->filename); + free(module->environment); + + for (size_t f = 0; f < module->num_functions; f++) + free(module->functions[f].name); + + free(module->functions); + + if (module->type == MODULE_PLAIN) { + for (size_t f = 0; f < module->handle.ast.num_functions; f++) { + ParseFunction *function = module->handle.ast.functions[f]; + + if (function) { + free_expression(function->expression); + free(function->name); + free(function); + } + } + + if (module->handle.ast.functions) + free(module->handle.ast.functions); + } + + free(module); + } + + free(state.modules); + + return state.program; +} diff --git a/src/load.h b/src/load.h new file mode 100644 index 0000000..5d6b00e --- /dev/null +++ b/src/load.h @@ -0,0 +1,19 @@ +#ifndef _LOAD_H_ +#define _LOAD_H_ + +#include +#include "api/vm.h" + +typedef struct +{ + void *api_library; + UwUVMFunction *main_function; + UwUVMFunction **functions; + size_t num_functions; + void **libraries; + size_t num_libraries; +} Program; + +Program load_program(const char *progname, const char *modname); + +#endif diff --git a/src/main.c b/src/main.c index 60c22ba..2a29d80 100644 --- a/src/main.c +++ b/src/main.c @@ -1,56 +1,11 @@ -#include "err.h" -#include "vm.h" +#include "common/err.h" +#include "run.h" int main(int argc, char *argv[]) { if (argc < 2) error("usage: %s \n", argv[0]); - vm_run_file(argv[0], argv[1]); + run_module(argv[0], argv[1], argc > 2 ? (size_t) argc - 2 : 0, &argv[2]); return 0; } - -/* - -0123 -"asd" -$arg -&fnname -func(asd) - -:int:add -:str:cat -:boo:and -:arr:arr -:set:set - -integer::add() -integer::sub() -integer::mul() -integer::div() -integer::mod() -integer::pow() - -string::concat() -string::split() -string::find() - -array::array() -array::select() -array::insert() -array::length() -array::reduce() -array::map() - -set::set() -set::pair() -set::select() -set::insert() -set::remove() -set::contains() - -boolean::and() -boolean::or() -boolean::xor() - -*/ diff --git a/src/parse.c b/src/parse.c index c8b430d..ed09de9 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1,7 +1,7 @@ #include #include #include -#include "err.h" +#include "common/err.h" #include "parse.h" #define DEBUG 0 diff --git a/src/parse.h b/src/parse.h index 7aca6af..46f4542 100644 --- a/src/parse.h +++ b/src/parse.h @@ -3,11 +3,11 @@ #include #include -#include "expression.h" +#include "api/vm.h" typedef struct ParseExpression { - ExpressionType type; + UwUVMExpressionType type; union { int int_value; diff --git a/src/run.c b/src/run.c new file mode 100644 index 0000000..7733c8d --- /dev/null +++ b/src/run.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include "common/err.h" +#include "load.h" +#include "run.h" + +static void free_expression(UwUVMExpression *expr) +{ + if (expr->type == EX_FNCALL) { + for (size_t i = 0; i < expr->value.cll_value.num_args; i++) + free_expression(&expr->value.cll_value.args[i]); + + free(expr->value.cll_value.args); + } + + if (expr->type == EX_STRLIT) + free(expr->value.str_value); +} + +void run_module(const char *progname, const char *modname, size_t num_args, char *args[]) +{ + (void) num_args; + (void) args; + + Program program = load_program(progname, modname); + + UwUVMValue (*uwuvm_call_function)(UwUVMFunction *, size_t, UwUVMExpression *, UwUVMArgs *) = dlsym(program.api_library, "uwuvm_call_function"); + 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); + + UwUVMExpression arg_expressions[num_args]; + + for (size_t i = 0; i < num_args; i++) + arg_expressions[i] = (UwUVMExpression) { + .type = EX_STRLIT, + .value = { + .str_value = args[i], + }, + }; + + UwUVMValue result = uwuvm_call_function(program.main_function, num_args, arg_expressions, NULL); + + char *str = uwuvm_print_value(result); + printf("%s\n", str); + free(str); + + uwuvm_delet_value(result); + + for (size_t i = 0; i < program.num_functions; i++) { + UwUVMFunction *function = program.functions[i]; + + if (function->type == MODULE_PLAIN) { + free_expression(function->value.plain); + free(function->value.plain); + } + + free(function); + } + + free(program.functions); + + for (size_t i = 0; i < program.num_libraries; i++) + dlclose(program.libraries[i]); + + if (program.libraries) + free(program.libraries); + + dlclose(program.api_library); +} diff --git a/src/run.h b/src/run.h new file mode 100644 index 0000000..010dec0 --- /dev/null +++ b/src/run.h @@ -0,0 +1,8 @@ +#ifndef _RUN_H_ +#define _RUN_H_ + +#include + +void run_module(const char *progname, const char *modname, size_t num_args, char *args[]); + +#endif diff --git a/src/util.h b/src/util.h deleted file mode 100644 index b0baa37..0000000 --- a/src/util.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include -#include - -static inline char *asprintf_wrapper(const char *format, ...) -{ - va_list args; - va_start(args, format); - char *ptr; - vasprintf(&ptr, format, args); - va_end(args); - return ptr; -} - -#endif diff --git a/src/vm.c b/src/vm.c deleted file mode 100644 index 8b1b13a..0000000 --- a/src/vm.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include "collect.h" -#include "vm.h" - -static void free_expression(UwUVMExpression *expr) -{ - if (expr->type == EX_FNCALL) { - for (size_t i = 0; i < expr->value.cll_value.num_args; i++) - free_expression(&expr->value.cll_value.args[i]); - - free(expr->value.cll_value.args); - } - - if (expr->type == EX_STRLIT) - free(expr->value.str_value); -} - -void vm_run_file(const char *progname, const char *modname) -{ - UwUVMProgram program = create_program(progname, modname); - UwUVMValue result = ((UwUVMValue (*)(UwUVMFunction *, size_t, UwUVMExpression *, UwUVMArgs *)) dlsym(program.api_library, "uwuvm_call_function"))(program.main_function, 0, NULL, NULL); - - char *str = ((char *(*)(UwUVMValue)) dlsym(program.api_library, "uwuvm_print_value"))(result); - - printf("%s\n", str); - free(str); - - ((void (*)(UwUVMValue)) dlsym(program.api_library, "uwuvm_delet_value"))(result); - - for (size_t i = 0; i < program.num_functions; i++) { - UwUVMFunction *function = program.functions[i]; - - if (function->type == MODULE_PLAIN) { - free_expression(function->value.plain); - free(function->value.plain); - } - - free(function); - } - - free(program.functions); - - for (size_t i = 0; i < program.num_libraries; i++) - dlclose(program.libraries[i]); - - if (program.libraries) - free(program.libraries); - - dlclose(program.api_library); -} diff --git a/src/vm.h b/src/vm.h deleted file mode 100644 index 5e23c8b..0000000 --- a/src/vm.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _VM_H_ -#define _VM_H_ - -void vm_run_file(const char *progname, const char *modname); - -#endif diff --git a/std/bool.c b/std/bool.c index 4386dc3..349e1c9 100644 --- a/std/bool.c +++ b/std/bool.c @@ -1,10 +1,9 @@ #include #include -#include "../src/err.h" -#include "../api/vm.h" -#include "../api/util.h" -#include "../api/bool.h" - +#include "common/err.h" +#include "api/vm.h" +#include "api/util.h" +#include "api/bool.h" static inline bool get_bool_arg(UwUVMArgs *args, size_t i) { diff --git a/std/int.c b/std/int.c index 6857f26..22af320 100644 --- a/std/int.c +++ b/std/int.c @@ -1,10 +1,10 @@ #include #include -#include "../src/err.h" -#include "../api/vm.h" -#include "../api/int.h" -#include "../api/bool.h" -#include "../api/util.h" +#include "common/err.h" +#include "api/vm.h" +#include "api/int.h" +#include "api/bool.h" +#include "api/util.h" typedef enum { diff --git a/std/nil.c b/std/nil.c index 599e3d4..93172eb 100644 --- a/std/nil.c +++ b/std/nil.c @@ -1,6 +1,6 @@ -#include "../src/err.h" -#include "../api/nil.h" -#include "../api/util.h" +#include "common/err.h" +#include "api/nil.h" +#include "api/util.h" UwUVMValue uwu_nil(UwUVMArgs *args) { diff --git a/std/ref.c b/std/ref.c index f82bb50..62c0a52 100644 --- a/std/ref.c +++ b/std/ref.c @@ -1,6 +1,6 @@ -#include "../src/err.h" -#include "../api/ref.h" -#include "../api/util.h" +#include "common/err.h" +#include "api/ref.h" +#include "api/util.h" UwUVMValue uwu_call(UwUVMArgs *args) { diff --git a/std/str.c b/std/str.c index 953e8c0..a0e4edd 100644 --- a/std/str.c +++ b/std/str.c @@ -1,8 +1,8 @@ #include #include -#include "../api/vm.h" -#include "../api/str.h" -#include "../api/util.h" +#include "api/vm.h" +#include "api/str.h" +#include "api/util.h" UwUVMValue uwu_cat(UwUVMArgs *args) {