aboutsummaryrefslogtreecommitdiff
path: root/typecheck.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-06-16 15:12:00 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-06-16 15:12:00 -0400
commit7a53e10826e583b4fc00d032eeecada2cf19e9e2 (patch)
tree1acc23774ce1accf83ba28151b33eedc67d8b242 /typecheck.c
parent729d856139567d8ab458f24e10a8e714251deff1 (diff)
Fix issue with type namespaces not getting properly prefixed by library
namespace
Diffstat (limited to 'typecheck.c')
-rw-r--r--typecheck.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/typecheck.c b/typecheck.c
index 31fdfc77..8e4bfd7d 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -121,7 +121,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
ast_t *ast = parse_file(f, NULL);
if (!ast) errx(1, "Could not compile!");
- return load_module_env(env, heap_strf("%s$", name), ast);
+ return load_module_env(env, ast);
} else if (module_ast->tag == Use) {
const char *libname = Match(module_ast, Use)->name;
const char *files_filename = heap_strf("%s/lib%s.files", libname, libname);
@@ -131,7 +131,13 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
file_t *files_f = load_file(resolved_path);
if (!files_f) errx(1, "Couldn't open file: %s", resolved_path);
- env_t *ret_env = fresh_scope(env);
+ env_t *module_env = fresh_scope(env);
+ char *libname_id = heap_str(libname);
+ for (char *c = libname_id; *c; c++) {
+ if (!isalnum(*c) && *c != '_')
+ *c = '_';
+ }
+ module_env->namespace = new(namespace_t, .name=libname_id);
for (int64_t i = 1; i <= files_f->num_lines; i++) {
const char *line = get_line(files_f, i);
line = heap_strn(line, strcspn(line, "\r\n"));
@@ -144,23 +150,23 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
ast_t *ast = parse_file(tm_f, NULL);
if (!ast) errx(1, "Could not compile!");
- env_t *tmp_env = fresh_scope(env);
- char *prefix = heap_strf("%s$%s$", libname, file_base_name(line));
- for (char *p = prefix; *p; p++) {
+ env_t *module_file_env = fresh_scope(env);
+ char *file_prefix = heap_str(file_base_name(line));
+ for (char *p = file_prefix; *p; p++) {
if (!isalnum(*p) && *p != '_' && *p != '$')
*p = '_';
}
- tmp_env->file_prefix = prefix;
- tmp_env->imports = new(table_t);
- env_t *subenv = load_module_env(tmp_env, prefix, ast);
+ module_file_env->namespace = new(namespace_t, .name=file_prefix, .parent=module_env->namespace);
+ module_file_env->imports = new(table_t);
+ env_t *subenv = load_module_env(module_file_env, ast);
for (int64_t j = 0; j < subenv->locals->entries.length; j++) {
struct {
const char *name; binding_t *binding;
} *entry = subenv->locals->entries.data + j*subenv->locals->entries.stride;
- set_binding(ret_env, entry->name, entry->binding);
+ set_binding(module_env, entry->name, entry->binding);
}
}
- return ret_env;
+ return module_env;
} else {
code_err(module_ast, "This is not a module import");
}
@@ -181,7 +187,8 @@ void prebind_statement(env_t *env, ast_t *statement)
env_t *ns_env = namespace_env(env, def->name);
type_t *type = Type(StructType, .name=def->name, .opaque=true, .env=ns_env); // placeholder
Table$str_set(env->types, def->name, type);
- set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .code=CORD_all(env->file_prefix, def->name)));
+ set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
+ .code=CORD_all(namespace_prefix(env->namespace), def->name)));
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
prebind_statement(ns_env, stmt->ast);
break;
@@ -194,7 +201,7 @@ void prebind_statement(env_t *env, ast_t *statement)
env_t *ns_env = namespace_env(env, def->name);
type_t *type = Type(EnumType, .name=def->name, .opaque=true, .env=ns_env); // placeholder
Table$str_set(env->types, def->name, type);
- set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .code=CORD_all(env->file_prefix, def->name)));
+ set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .code=CORD_all(namespace_prefix(env->namespace), def->name)));
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
prebind_statement(ns_env, stmt->ast);
break;
@@ -207,7 +214,7 @@ void prebind_statement(env_t *env, ast_t *statement)
env_t *ns_env = namespace_env(env, def->name);
type_t *type = Type(TextType, .lang=def->name, .env=ns_env);
Table$str_set(env->types, def->name, type);
- set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .code=CORD_all(env->file_prefix, def->name)));
+ set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .code=CORD_all(namespace_prefix(env->namespace), def->name)));
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
prebind_statement(ns_env, stmt->ast);
break;
@@ -233,7 +240,8 @@ void bind_statement(env_t *env, ast_t *statement)
else
bind_statement(env, decl->value);
type_t *type = get_type(env, decl->value);
- CORD code = CORD_cat(env->scope_prefix ? env->scope_prefix : "$", name);
+ CORD prefix = namespace_prefix(env->namespace);
+ CORD code = CORD_cat(prefix ? prefix : "$", name);
set_binding(env, name, new(binding_t, .type=type, .code=code));
break;
}
@@ -244,7 +252,7 @@ void bind_statement(env_t *env, ast_t *statement)
code_err(def->name, "A %T called '%s' has already been defined", get_binding(env, name)->type, name);
type_t *type = get_function_def_type(env, statement);
bool is_private = (name[0] == '_');
- CORD code = is_private ? CORD_cat("$", name) : CORD_all(env->file_prefix, env->scope_prefix, name);
+ CORD code = is_private ? CORD_cat("$", name) : CORD_all(namespace_prefix(env->namespace), name);
set_binding(env, name, new(binding_t, .type=type, .code=code));
break;
}
@@ -310,9 +318,9 @@ void bind_statement(env_t *env, ast_t *statement)
for (tag_t *tag = tags; tag; tag = tag->next) {
if (Match(tag->type, StructType)->fields) { // Constructor:
type_t *constructor_t = Type(FunctionType, .args=Match(tag->type, StructType)->fields, .ret=type);
- set_binding(ns_env, tag->name, new(binding_t, .type=constructor_t, .code=CORD_all(env->file_prefix, def->name, "$tagged$", tag->name)));
+ set_binding(ns_env, tag->name, new(binding_t, .type=constructor_t, .code=CORD_all(namespace_prefix(env->namespace), def->name, "$tagged$", tag->name)));
} else { // Empty singleton value:
- CORD code = CORD_all("(", env->file_prefix, def->name, "_t){", env->file_prefix, def->name, "$tag$", tag->name, "}");
+ CORD code = CORD_all("(", namespace_prefix(env->namespace), def->name, "_t){", namespace_prefix(env->namespace), def->name, "$tag$", tag->name, "}");
set_binding(ns_env, tag->name, new(binding_t, .type=type, .code=code));
}
Table$str_set(env->types, heap_strf("%s$%s", def->name, tag->name), tag->type);
@@ -331,7 +339,7 @@ void bind_statement(env_t *env, ast_t *statement)
set_binding(ns_env, "from_unsafe_text",
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type),
- .code=CORD_all("(", env->file_prefix, def->name, "_t)")));
+ .code=CORD_all("(", namespace_prefix(env->namespace), def->name, "_t)")));
set_binding(ns_env, "text_content",
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type),
.code="(Text_t)"));