]> git.lizzy.rs Git - uwu-lang.git/blobdiff - src/load.c
Redesign function names
[uwu-lang.git] / src / load.c
index e5f683646a6a80da44b2926caa47aadca6813c4f..4a05915e28320b6949ed587f15f9668f683d5344 100644 (file)
@@ -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];