X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fload.c;fp=src%2Fload.c;h=4a05915e28320b6949ed587f15f9668f683d5344;hb=6ec67846ffadb5bd1be13d5a7ea3abcf67f1c536;hp=e5f683646a6a80da44b2926caa47aadca6813c4f;hpb=8e3ed7630c7383869b6e16b494d4288c4e094dd3;p=uwu-lang.git diff --git a/src/load.c b/src/load.c index e5f6836..4a05915 100644 --- a/src/load.c +++ b/src/load.c @@ -35,31 +35,35 @@ typedef struct typedef struct { - char *path; // path without file extension - char *filename; // path with file extension - char *environment; // directory path + char *path; // path without file extension + char *filename; // path with file extension + char *environment; // directory path - UwUVMModuleType type; // native (.so) or plain (.uwu) + 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) + 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) + 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 + Module **modules; // loaded modules + size_t num_modules; // count for modules - char *std_path; // path to standard library + char **module_paths; // module search paths + size_t num_module_paths; // count for module_paths + char *module_paths_str; // module search paths, stringified - Program program; // the result program + char *std_path; // path to standard library + + Program program; // the result program } LoadState; // functions @@ -88,7 +92,7 @@ static inline char *get_filename(const char *module_path) } // module_path is a mallocated string -static Module *require_module(LoadState *state, char *module_path) +static Module *load_module(LoadState *state, char *module_path) { for (size_t i = 0; i < state->num_modules; i++) { Module *module = state->modules[i]; @@ -101,8 +105,10 @@ static Module *require_module(LoadState *state, char *module_path) char *filename = get_filename(module_path); - if (! filename) - error("module error: module %s not found\n", module_path); + if (! filename) { + free(module_path); + return NULL; + } size_t filename_len = strlen(filename); UwUVMModuleType type = (filename_len >= 3 && strcmp(filename + filename_len - 3, ".so") == 0) ? MODULE_NATIVE : MODULE_PLAIN; @@ -163,10 +169,10 @@ static UwUVMFunction *resolve_function(LoadState *state, Module *caller_module, size_t len = strlen(full_name); const char *fnname; - for (fnname = &full_name[len - 1]; *fnname != ':' && fnname > full_name; fnname--) + for (fnname = &full_name[len - 1]; *fnname != '.' && fnname > full_name; fnname--) ; - if (*fnname == ':') + if (*fnname == '.') fnname++; if (*fnname == '\0') @@ -177,12 +183,18 @@ static UwUVMFunction *resolve_function(LoadState *state, Module *caller_module, if (fnname == full_name) { callee_module = caller_module; } else { - const char *caller_path = caller_module->environment; + char **environments = state->module_paths; + size_t num_environments = state->num_module_paths; + char *environments_str = state->module_paths_str; + const char *callee_name = full_name; - if (*callee_name == ':') { - caller_path = state->std_path; + if (*callee_name == '.') { callee_name++; + + environments = &caller_module->environment; + num_environments = 1; + environments_str = caller_module->environment; } size_t path_len = fnname - callee_name; @@ -190,10 +202,15 @@ static UwUVMFunction *resolve_function(LoadState *state, Module *caller_module, for (size_t i = 0; i < path_len; i++) callee_path[i] = (i == path_len - 1) ? '\0' - : (callee_name[i] == ':') ? '/' + : (callee_name[i] == '.') ? '/' : callee_name[i]; - callee_module = require_module(state, asprintf_wrapper("%s/%s", caller_path, callee_path)); + for (size_t i = 0; i < num_environments; i++) + if ((callee_module = load_module(state, asprintf_wrapper("%s/%s", environments[i], callee_path)))) + break; + + if (! callee_module) + error("module error: no module %s in path %s\n", callee_path, environments_str); } return require_function(state, callee_module, fnname); @@ -301,7 +318,6 @@ Program load_program(const char *progname, const char *modname) 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, @@ -312,10 +328,44 @@ Program load_program(const char *progname, const char *modname) }, }; + char *uwu_module_path = getenv("UWU_MODULE_PATH"); + + if (uwu_module_path) { + char *uwu_module_path_ptr = state.module_paths_str = uwu_module_path; + char *uwu_module_path_base_ptr = uwu_module_path_ptr; + size_t uwu_module_path_len = 1; + + state.num_module_paths = 0; + state.module_paths = NULL; + + for (;; uwu_module_path_ptr++, uwu_module_path_len++) { + if (*uwu_module_path_ptr == '\0' || *uwu_module_path_ptr == ':') { + state.module_paths = realloc(state.module_paths, sizeof(char **) * ++state.num_module_paths); + strncpy(state.module_paths[state.num_module_paths - 1] = malloc(uwu_module_path_len), uwu_module_path_base_ptr, uwu_module_path_len)[uwu_module_path_len - 1] = '\0'; + + uwu_module_path_len = 0; + uwu_module_path_base_ptr = uwu_module_path_ptr + 1; + } + + if (*uwu_module_path_ptr == '\0') + break; + } + } else { + state.module_paths_str = asprintf_wrapper("%s/std", prog_dirname); + state.num_module_paths = 1; + state.module_paths = malloc(sizeof(char **)); + state.module_paths[0] = state.module_paths_str; + } + free(prog_dirname); free(api_path); - state.program.main_function = require_function(&state, require_module(&state, strdup(modname)), "main"); + Module *main_module = load_module(&state, strdup(modname)); + + if (! main_module) + error("module error: requested module %s not found\n", modname); + + state.program.main_function = require_function(&state, main_module, "main"); while (true) { bool fully_loaded = true; @@ -337,7 +387,10 @@ Program load_program(const char *progname, const char *modname) break; } - free(state.std_path); + for (size_t i = 0; i < state.num_module_paths; i++) + free(state.module_paths[i]); + + free(state.module_paths); for (size_t i = 0; i < state.num_modules; i++) { Module *module = state.modules[i];