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
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
To run:
```
-./uwu <module>
+./uwu <module> <args>
```
`<module>` is a path relative to the current directory.
#include <stdlib.h>
-#include "../src/util.h"
+#include "common/str.h"
#include "int.h"
UwUVMValue uwuint_create(int value)
-#include "../src/util.h"
+#include "common/str.h"
#include "ref.h"
UwUVMValue uwuref_create(UwUVMFunction *value)
-#include "../src/err.h"
+#include "common/err.h"
#include "util.h"
#include "bool.h"
#include <stdio.h>
#include <stdlib.h>
-#include "../src/err.h"
+#include "common/err.h"
#include "vm.h"
#include "str.h"
#include "ref.h"
#include <stddef.h>
#include <stdbool.h>
-#include "../src/expression.h"
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);
typedef struct UwUVMExpression
{
- ExpressionType type;
+ UwUVMExpressionType type;
union
{
struct
} 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);
--- /dev/null
+#ifndef _ERR_H_
+#define _ERR_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+static inline void error(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ exit(1);
+}
+
+#endif
--- /dev/null
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+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
--- /dev/null
+main :str:cat(
+ $0,
+ $1,
+ $2
+)
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <libgen.h>
-#include <dlfcn.h>
-#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;
-}
+++ /dev/null
-#ifndef _COLLECT_H_
-#define _COLLECT_H_
-
-#include "../api/vm.h"
-
-UwUVMProgram create_program(const char *progname, const char *modname);
-
-#endif
+++ /dev/null
-#ifndef _ERR_H_
-#define _ERR_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-static inline void error(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- exit(1);
-}
-
-#endif
+++ /dev/null
-#ifndef _EXPRESSION_H_
-#define _EXPRESSION_H_
-
-typedef enum
-{
- EX_UNINIT,
- EX_INTLIT,
- EX_STRLIT,
- EX_ARGNUM,
- EX_FNNAME,
- EX_FNCALL,
-} ExpressionType;
-
-#endif
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <dlfcn.h>
+#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;
+}
--- /dev/null
+#ifndef _LOAD_H_
+#define _LOAD_H_
+
+#include <stddef.h>
+#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
-#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 <module>\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()
-
-*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
-#include "err.h"
+#include "common/err.h"
#include "parse.h"
#define DEBUG 0
#include <stddef.h>
#include <stdbool.h>
-#include "expression.h"
+#include "api/vm.h"
typedef struct ParseExpression
{
- ExpressionType type;
+ UwUVMExpressionType type;
union
{
int int_value;
--- /dev/null
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+#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);
+}
--- /dev/null
+#ifndef _RUN_H_
+#define _RUN_H_
+
+#include <stddef.h>
+
+void run_module(const char *progname, const char *modname, size_t num_args, char *args[]);
+
+#endif
+++ /dev/null
-#ifndef _UTIL_H_
-#define _UTIL_H_
-
-#include <stdio.h>
-#include <stdarg.h>
-
-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
+++ /dev/null
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <stdio.h>
-#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);
-}
+++ /dev/null
-#ifndef _VM_H_
-#define _VM_H_
-
-void vm_run_file(const char *progname, const char *modname);
-
-#endif
#include <stdio.h>
#include <stdlib.h>
-#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)
{
#include <stdio.h>
#include <stdlib.h>
-#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
{
-#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)
{
-#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)
{
#include <string.h>
#include <stdlib.h>
-#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)
{