aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-05-17 16:13:55 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-05-17 16:13:55 -0400
commit13e7d04a74f7ad0b9b9dc96f681d091b65dce5ec (patch)
tree321c63e528b939beab2f6f2c46192ab507546735 /src
parent8febea9aebe05644731bb68c297d3d13649a8dcb (diff)
Add `modules.ini` file for import aliases, as well as default aliases
for the built-in modules.
Diffstat (limited to 'src')
-rw-r--r--src/compile.c14
-rw-r--r--src/environment.c44
-rw-r--r--src/environment.h1
-rw-r--r--src/stdlib/paths.c13
-rw-r--r--src/stdlib/paths.h3
-rw-r--r--src/tomo.c21
-rw-r--r--src/typecheck.c5
7 files changed, 76 insertions, 25 deletions
diff --git a/src/compile.c b/src/compile.c
index 98c0bdb0..410ee364 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -1976,8 +1976,9 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
CORD suffix = get_id_suffix(Path$as_c_string(path));
return with_source_info(env, ast, CORD_all("$initialize", suffix, "();\n"));
} else if (use->what == USE_MODULE) {
+ const char *name = module_alias(ast);
glob_t tm_files;
- if (glob(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
+ if (glob(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", name, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
code_err(ast, "Could not find library");
CORD initialization = CORD_EMPTY;
@@ -4483,16 +4484,17 @@ CORD compile_statement_type_header(env_t *env, Path_t header_path, ast_t *ast)
Path_t build_dir = Path$resolved(Path$parent(header_path), Path$current_dir());
switch (use->what) {
case USE_MODULE: {
+ const char *name = module_alias(ast);
glob_t tm_files;
- if (glob(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
+ if (glob(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", name, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
code_err(ast, "Could not find library");
CORD includes = CORD_EMPTY;
for (size_t i = 0; i < tm_files.gl_pathc; i++) {
const char *filename = tm_files.gl_pathv[i];
Path_t tm_file = Path$from_str(filename);
- Path_t lib_build_dir = Path$with_component(Path$parent(tm_file), Text(".build"));
- Path_t header = Path$with_component(lib_build_dir, Texts(Path$base_name(tm_file), Text(".h")));
+ Path_t lib_build_dir = Path$sibling(tm_file, Text(".build"));
+ Path_t header = Path$child(lib_build_dir, Texts(Path$base_name(tm_file), Text(".h")));
includes = CORD_all(includes, "#include \"", Path$as_c_string(header), "\"\n");
}
globfree(&tm_files);
@@ -4500,8 +4502,8 @@ CORD compile_statement_type_header(env_t *env, Path_t header_path, ast_t *ast)
}
case USE_LOCAL: {
Path_t used_path = Path$resolved(Path$from_str(use->path), source_dir);
- Path_t used_build_dir = Path$with_component(Path$parent(used_path), Text(".build"));
- Path_t used_header_path = Path$with_component(used_build_dir, Texts(Path$base_name(used_path), Text(".h")));
+ Path_t used_build_dir = Path$sibling(used_path, Text(".build"));
+ Path_t used_header_path = Path$child(used_build_dir, Texts(Path$base_name(used_path), Text(".h")));
return CORD_all("#include \"", Path$as_c_string(Path$relative_to(used_header_path, build_dir)), "\"\n");
}
case USE_HEADER:
diff --git a/src/environment.c b/src/environment.c
index a34e0907..4fdfbd4e 100644
--- a/src/environment.c
+++ b/src/environment.c
@@ -7,8 +7,12 @@
#include "cordhelpers.h"
#include "environment.h"
#include "parse.h"
+#include "stdlib/c_strings.h"
#include "stdlib/datatypes.h"
+#include "stdlib/memory.h"
#include "stdlib/paths.h"
+#include "stdlib/pointers.h"
+#include "stdlib/simpleparse.h"
#include "stdlib/tables.h"
#include "stdlib/text.h"
#include "stdlib/util.h"
@@ -547,12 +551,12 @@ CORD get_id_suffix(const char *filename)
{
assert(filename);
Path_t path = Path$from_str(filename);
- Path_t build_dir = Path$with_component(Path$parent(path), Text(".build"));
+ Path_t build_dir = Path$sibling(path, Text(".build"));
if (mkdir(Path$as_c_string(build_dir), 0755) != 0) {
if (!Path$is_directory(build_dir, true))
err(1, "Could not make .build directory");
}
- Path_t id_file = Path$with_component(build_dir, Texts(Path$base_name(path), Text$from_str(".id")));
+ Path_t id_file = Path$child(build_dir, Texts(Path$base_name(path), Text$from_str(".id")));
OptionalText_t id = Path$read(id_file);
if (id.length < 0) err(1, "Could not read ID file: ", id_file);
return Text$as_c_string(Texts(Text("$"), id));
@@ -789,4 +793,40 @@ void set_binding(env_t *env, const char *name, type_t *type, CORD code)
Table$str_set(env->locals, name, new(binding_t, .type=type, .code=code));
}
+const char *module_alias(ast_t *use)
+{
+ static Table_t cache = {};
+ const char **cached = Table$get(cache, &use, Table$info(Pointer$info("@", &Memory$info), &CString$info));
+ if (cached) return *cached;
+ const char *name = Match(use, Use)->path;
+ const char *alias = name;
+ if (streq(name, "commands")) alias = "commands_v1.0";
+ else if (streq(name, "random")) alias = "random_v1.0";
+ else if (streq(name, "base64")) alias = "base64_v1.0";
+ else if (streq(name, "core")) alias = "core_v1.0";
+ else if (streq(name, "patterns")) alias = "patterns_v1.0";
+ else if (streq(name, "pthreads")) alias = "pthreads_v1.0";
+ else if (streq(name, "shell")) alias = "shell_v1.0";
+ else if (streq(name, "time")) alias = "time_v1.0";
+ else if (streq(name, "uuid")) alias = "uuid_v1.0";
+ else {
+ Path_t alias_file = Path$sibling(Path$from_str(use->file->filename), Text("modules.ini"));
+ OptionalClosure_t by_line = Path$by_line(alias_file);
+ if (by_line.fn) {
+ OptionalText_t (*next_line)(void*) = by_line.fn;
+ for (Text_t line; (line=next_line(by_line.userdata)).length >= 0; ) {
+ char *line_str = Text$as_c_string(line);
+ const char *line_alias = NULL, *full_version = NULL;
+ if (!strparse(line_str, &line_alias, "=", &full_version)
+ && streq(line_alias, name)) {
+ alias = full_version;
+ break;
+ }
+ }
+ }
+ }
+ Table$set(&cache, &use, &alias, Table$info(Pointer$info("@", &Memory$info), &CString$info));
+ return alias;
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/environment.h b/src/environment.h
index a89935e6..474bab61 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -94,5 +94,6 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name);
extern type_t *TEXT_TYPE;
extern type_t *PATH_TYPE;
extern type_t *PATH_TYPE_TYPE;
+const char *module_alias(ast_t *use);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index 6b16916c..5047d615 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -609,20 +609,25 @@ public Text_t Path$extension(Path_t path, bool full)
return Text$from_str(extension);
}
-public Path_t Path$with_component(Path_t path, Text_t component)
+public Path_t Path$child(Path_t path, Text_t name)
{
- if (Text$has(component, Text("/")) || Text$has(component, Text(";")))
- fail("Path component has invalid characters: ", component);
+ if (Text$has(name, Text("/")) || Text$has(name, Text(";")))
+ fail("Path name has invalid characters: ", name);
Path_t result = {
.type.$tag=path.type.$tag,
.components=path.components,
};
LIST_INCREF(result.components);
- List$insert(&result.components, &component, I(0), sizeof(Text_t));
+ List$insert(&result.components, &name, I(0), sizeof(Text_t));
clean_components(&result.components);
return result;
}
+public Path_t Path$sibling(Path_t path, Text_t name)
+{
+ return Path$child(Path$parent(path), name);
+}
+
public Path_t Path$with_extension(Path_t path, Text_t extension, bool replace)
{
if (path.components.length == 0)
diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h
index 31d676b7..4f94d3e4 100644
--- a/src/stdlib/paths.h
+++ b/src/stdlib/paths.h
@@ -51,7 +51,8 @@ Path_t Path$write_unique_bytes(Path_t path, List_t bytes);
Path_t Path$parent(Path_t path);
Text_t Path$base_name(Path_t path);
Text_t Path$extension(Path_t path, bool full);
-Path_t Path$with_component(Path_t path, Text_t component);
+Path_t Path$child(Path_t path, Text_t name);
+Path_t Path$sibling(Path_t path, Text_t name);
Path_t Path$with_extension(Path_t path, Text_t extension, bool replace);
Path_t Path$current_dir(void);
Closure_t Path$by_line(Path_t path);
diff --git a/src/tomo.c b/src/tomo.c
index e11dbd23..3fcd0ade 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -287,7 +287,7 @@ int main(int argc, char *argv[])
for (int64_t i = 0; i < files.length; i++) {
Path_t *path = (Path_t*)(files.data + i*files.stride);
if (Path$is_directory(*path, true))
- *path = Path$with_component(*path, Texts(Path$base_name(*path), Text(".tm")));
+ *path = Path$child(*path, Texts(Path$base_name(*path), Text(".tm")));
*path = Path$resolved(*path, cur_dir);
if (!Path$exists(*path))
@@ -363,17 +363,17 @@ void wait_for_child_success(pid_t child)
Path_t build_file(Path_t path, const char *extension)
{
- Path_t build_dir = Path$with_component(Path$parent(path), Text(".build"));
+ Path_t build_dir = Path$sibling(path, Text(".build"));
if (mkdir(Path$as_c_string(build_dir), 0755) != 0) {
if (!Path$is_directory(build_dir, true))
err(1, "Could not make .build directory");
}
- return Path$with_component(build_dir, Texts(Path$base_name(path), Text$from_str(extension)));
+ return Path$child(build_dir, Texts(Path$base_name(path), Text$from_str(extension)));
}
static Text_t get_version_suffix(Path_t lib_dir)
{
- Path_t changes_file = Path$with_component(lib_dir, Text("CHANGES.md"));
+ Path_t changes_file = Path$child(lib_dir, Text("CHANGES.md"));
OptionalText_t changes = Path$read(changes_file);
if (changes.length <= 0) {
print_err("I couldn't find a valid CHANGES.md for the library in ", lib_dir, "\n"
@@ -399,7 +399,7 @@ void build_library(Path_t lib_dir)
print_err("Not a valid directory: ", lib_dir);
Text_t lib_dir_name = Path$base_name(lib_dir);
- List_t tm_files = Path$glob(Path$with_component(lib_dir, Text("[!._0-9]*.tm")));
+ List_t tm_files = Path$glob(Path$child(lib_dir, Text("[!._0-9]*.tm")));
env_t *env = fresh_scope(global_env(source_mapping));
List_t object_files = {},
extra_ldlibs = {};
@@ -407,7 +407,7 @@ void build_library(Path_t lib_dir)
compile_files(env, tm_files, &object_files, &extra_ldlibs);
Text_t version_suffix = get_version_suffix(lib_dir);
- Path_t shared_lib = Path$with_component(lib_dir, Texts(Text("lib"), lib_dir_name, version_suffix, Text(SHARED_SUFFIX)));
+ Path_t shared_lib = Path$child(lib_dir, Texts(Text("lib"), lib_dir_name, version_suffix, Text(SHARED_SUFFIX)));
if (!is_stale_for_any(shared_lib, object_files)) {
if (verbose) whisper("Unchanged: ", shared_lib);
return;
@@ -435,7 +435,7 @@ void install_library(Path_t lib_dir)
{
Text_t lib_dir_name = Path$base_name(lib_dir);
Text_t version_suffix = get_version_suffix(lib_dir);
- Path_t dest = Path$with_component(Path$from_str(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed"), Texts(lib_dir_name, version_suffix));
+ Path_t dest = Path$child(Path$from_str(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed"), Texts(lib_dir_name, version_suffix));
if (!Path$equal_values(lib_dir, dest)) {
if (verbose) whisper("Clearing out any pre-existing version of ", lib_dir_name);
xsystem(as_owner, "rm -rf '", dest, "'");
@@ -619,13 +619,14 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l
break;
}
case USE_MODULE: {
+ const char *name = module_alias(stmt_ast);
Text_t lib = Texts(Text("-Wl,-rpath,'"),
- Text(TOMO_PREFIX "/share/tomo_"TOMO_VERSION"/installed/"), Text$from_str(use->path),
+ Text(TOMO_PREFIX "/share/tomo_"TOMO_VERSION"/installed/"), Text$from_str(name),
Text("' '" TOMO_PREFIX "/share/tomo_"TOMO_VERSION"/installed/"),
- Text$from_str(use->path), Text("/lib"), Text$from_str(use->path), Text(SHARED_SUFFIX "'"));
+ Text$from_str(name), Text("/lib"), Text$from_str(name), Text(SHARED_SUFFIX "'"));
Table$set(to_link, &lib, NULL, Table$info(&Text$info, &Void$info));
- List_t children = Path$glob(Path$from_str(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", use->path, "/*.tm")));
+ List_t children = Path$glob(Path$from_str(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", name, "/*.tm")));
for (int64_t i = 0; i < children.length; i++) {
Path_t *child = (Path_t*)(children.data + i*children.stride);
Table_t discarded = {.fallback=to_compile};
diff --git a/src/typecheck.c b/src/typecheck.c
index c80f6b2a..60cef3fc 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -182,12 +182,13 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
return load_module_env(env, ast);
}
case USE_MODULE: {
+ const char *name = module_alias(module_ast);
glob_t tm_files;
- if (glob(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
+ if (glob(String(TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/", name, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
code_err(module_ast, "Could not find library");
env_t *module_env = fresh_scope(env);
- Table$str_set(env->imports, use->path, module_env);
+ Table$str_set(env->imports, name, module_env);
for (size_t i = 0; i < tm_files.gl_pathc; i++) {
const char *filename = tm_files.gl_pathv[i];