Support library name as a separate environment field from namespace
This commit is contained in:
parent
7dcb5bea3f
commit
9f8be0c502
36
compile.c
36
compile.c
@ -20,7 +20,7 @@ static env_t *with_enum_scope(env_t *env, type_t *t);
|
||||
CORD compile_type_ast(env_t *env, type_ast_t *t)
|
||||
{
|
||||
switch (t->tag) {
|
||||
case VarTypeAST: return CORD_all(namespace_prefix(env->namespace), Match(t, VarTypeAST)->name, "_t");
|
||||
case VarTypeAST: return CORD_all(namespace_prefix(env->libname, env->namespace), Match(t, VarTypeAST)->name, "_t");
|
||||
case PointerTypeAST: return CORD_cat(compile_type_ast(env, Match(t, PointerTypeAST)->pointed), "*");
|
||||
case TableTypeAST: return "table_t";
|
||||
case ArrayTypeAST: return "array_t";
|
||||
@ -126,7 +126,7 @@ CORD compile_type(env_t *env, type_t *t)
|
||||
case NumType: return Match(t, NumType)->bits == 64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits);
|
||||
case TextType: {
|
||||
auto text = Match(t, TextType);
|
||||
return text->lang ? CORD_all(namespace_prefix(text->env->namespace->parent), text->lang, "_t") : "Text_t";
|
||||
return text->lang ? CORD_all(namespace_prefix(env->libname, text->env->namespace->parent), text->lang, "_t") : "Text_t";
|
||||
}
|
||||
case ArrayType: return "array_t";
|
||||
case TableType: return "table_t";
|
||||
@ -143,11 +143,11 @@ CORD compile_type(env_t *env, type_t *t)
|
||||
case PointerType: return CORD_cat(compile_type(env, Match(t, PointerType)->pointed), "*");
|
||||
case StructType: {
|
||||
auto s = Match(t, StructType);
|
||||
return CORD_all("struct ", namespace_prefix(s->env->namespace->parent), s->name, "_s");
|
||||
return CORD_all("struct ", namespace_prefix(env->libname, s->env->namespace->parent), s->name, "_s");
|
||||
}
|
||||
case EnumType: {
|
||||
auto e = Match(t, EnumType);
|
||||
return CORD_all(namespace_prefix(e->env->namespace->parent), e->name, "_t");
|
||||
return CORD_all(namespace_prefix(env->libname, e->env->namespace->parent), e->name, "_t");
|
||||
}
|
||||
case TypeInfoType: return "TypeInfo";
|
||||
default: compiler_err(NULL, NULL, NULL, "Compiling type is not implemented for type with tag %d", t->tag);
|
||||
@ -232,7 +232,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
||||
"switch (subject.$tag) {");
|
||||
for (when_clause_t *clause = when->clauses; clause; clause = clause->next) {
|
||||
const char *clause_tag_name = Match(clause->tag_name, Var)->name;
|
||||
code = CORD_all(code, "case ", namespace_prefix(enum_t->env->namespace), enum_t->name, "$tag$", clause_tag_name, ": {\n");
|
||||
code = CORD_all(code, "case ", namespace_prefix(env->libname, enum_t->env->namespace), enum_t->name, "$tag$", clause_tag_name, ": {\n");
|
||||
type_t *tag_type = NULL;
|
||||
for (tag_t *tag = enum_t->tags; tag; tag = tag->next) {
|
||||
if (streq(tag->name, clause_tag_name)) {
|
||||
@ -515,7 +515,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
||||
case LangDef: {
|
||||
auto def = Match(ast, LangDef);
|
||||
CORD_appendf(&env->code->typeinfos, "public const TypeInfo %r%s = {%zu, %zu, {.tag=TextInfo, .TextInfo={%r}}};\n",
|
||||
namespace_prefix(env->namespace), def->name, sizeof(CORD), __alignof__(CORD),
|
||||
namespace_prefix(env->libname, env->namespace), def->name, sizeof(CORD), __alignof__(CORD),
|
||||
Text$quoted(def->name, false));
|
||||
compile_namespace(env, def->name, def->namespace);
|
||||
return CORD_EMPTY;
|
||||
@ -523,7 +523,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
||||
case FunctionDef: {
|
||||
auto fndef = Match(ast, FunctionDef);
|
||||
bool is_private = Match(fndef->name, Var)->name[0] == '_';
|
||||
CORD name = is_private ? CORD_cat("$", Match(fndef->name, Var)->name) : compile(env, fndef->name);
|
||||
CORD name = compile(env, fndef->name);
|
||||
type_t *ret_t = fndef->ret_type ? parse_type_ast(env, fndef->ret_type) : Type(VoidType);
|
||||
|
||||
CORD arg_signature = "(";
|
||||
@ -1497,7 +1497,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
}
|
||||
case Lambda: {
|
||||
auto lambda = Match(ast, Lambda);
|
||||
CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env->namespace), lambda->id);
|
||||
CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env->libname, env->namespace), lambda->id);
|
||||
|
||||
env_t *body_scope = fresh_scope(env);
|
||||
for (arg_ast_t *arg = lambda->args; arg; arg = arg->next) {
|
||||
@ -1976,15 +1976,15 @@ CORD compile_type_info(env_t *env, type_t *t)
|
||||
return CORD_asprintf("&$%r", type_to_cord(t));
|
||||
case TextType: {
|
||||
auto text = Match(t, TextType);
|
||||
return text->lang ? CORD_all("(&", namespace_prefix(text->env->namespace->parent), text->lang, ")") : "&$Text";
|
||||
return text->lang ? CORD_all("(&", namespace_prefix(env->libname, text->env->namespace->parent), text->lang, ")") : "&$Text";
|
||||
}
|
||||
case StructType: {
|
||||
auto s = Match(t, StructType);
|
||||
return CORD_all("(&", namespace_prefix(s->env->namespace->parent), s->name, ")");
|
||||
return CORD_all("(&", namespace_prefix(env->libname, s->env->namespace->parent), s->name, ")");
|
||||
}
|
||||
case EnumType: {
|
||||
auto e = Match(t, EnumType);
|
||||
return CORD_all("(&", namespace_prefix(e->env->namespace->parent), e->name, ")");
|
||||
return CORD_all("(&", namespace_prefix(env->libname, e->env->namespace->parent), e->name, ")");
|
||||
}
|
||||
case ArrayType: {
|
||||
type_t *item_t = Match(t, ArrayType)->item_type;
|
||||
@ -2201,12 +2201,12 @@ CORD compile_file(env_t *env, ast_t *ast)
|
||||
} else if (is_private) {
|
||||
env->code->staticdefs = CORD_all(
|
||||
env->code->staticdefs,
|
||||
"static ", compile_type(env, t), " ", namespace_prefix(env->namespace), decl_name, " = ",
|
||||
"static ", compile_type(env, t), " ", namespace_prefix(env->libname, env->namespace), decl_name, " = ",
|
||||
compile(env, decl->value), ";\n");
|
||||
} else {
|
||||
env->code->staticdefs = CORD_all(
|
||||
env->code->staticdefs,
|
||||
compile_type(env, t), " ", namespace_prefix(env->namespace), decl_name, " = ",
|
||||
compile_type(env, t), " ", namespace_prefix(env->libname, env->namespace), decl_name, " = ",
|
||||
compile(env, decl->value), ";\n");
|
||||
}
|
||||
} else if (stmt->ast->tag == InlineCCode) {
|
||||
@ -2256,7 +2256,7 @@ CORD compile_statement_header(env_t *env, ast_t *ast)
|
||||
return code;
|
||||
} else {
|
||||
return CORD_all(
|
||||
code, "\n" "extern ", compile_declaration(env, t, CORD_cat(namespace_prefix(env->namespace), decl_name)), ";\n");
|
||||
code, "\n" "extern ", compile_declaration(env, t, CORD_cat(namespace_prefix(env->libname, env->namespace), decl_name)), ";\n");
|
||||
}
|
||||
}
|
||||
case StructDef: {
|
||||
@ -2268,8 +2268,8 @@ CORD compile_statement_header(env_t *env, ast_t *ast)
|
||||
case LangDef: {
|
||||
auto def = Match(ast, LangDef);
|
||||
return CORD_all(
|
||||
"typedef CORD ", namespace_prefix(env->namespace), def->name, "_t;\n",
|
||||
"extern const TypeInfo ", namespace_prefix(env->namespace), def->name, ";\n");
|
||||
"typedef CORD ", namespace_prefix(env->libname, env->namespace), def->name, "_t;\n",
|
||||
"extern const TypeInfo ", namespace_prefix(env->libname, env->namespace), def->name, ";\n");
|
||||
compile_namespace(env, def->name, def->namespace);
|
||||
return CORD_EMPTY;
|
||||
}
|
||||
@ -2288,12 +2288,12 @@ CORD compile_statement_header(env_t *env, ast_t *ast)
|
||||
|
||||
type_t *ret_t = fndef->ret_type ? parse_type_ast(env, fndef->ret_type) : Type(VoidType);
|
||||
CORD ret_type_code = compile_type(env, ret_t);
|
||||
CORD header = CORD_all(ret_type_code, " ", CORD_cat(namespace_prefix(env->namespace), decl_name), arg_signature, ";\n");
|
||||
CORD header = CORD_all(ret_type_code, " ", CORD_cat(namespace_prefix(env->libname, env->namespace), decl_name), arg_signature, ";\n");
|
||||
return header;
|
||||
}
|
||||
case Lambda: {
|
||||
auto lambda = Match(ast, Lambda);
|
||||
CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env->namespace), lambda->id);
|
||||
CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env->libname, env->namespace), lambda->id);
|
||||
table_t *closed_vars = get_closed_vars(env, ast);
|
||||
if (Table$length(*closed_vars) == 0) {
|
||||
return CORD_EMPTY;
|
||||
|
12
enums.c
12
enums.c
@ -23,7 +23,7 @@ static bool has_extra_data(tag_ast_t *tags)
|
||||
static CORD compile_str_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, EnumDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
CORD str_func = CORD_all("static CORD ", full_name, "$as_text(", full_name, "_t *obj, bool use_color) {\n"
|
||||
"\tif (!obj) return \"", def->name, "\";\n"
|
||||
"switch (obj->$tag) {\n");
|
||||
@ -57,7 +57,7 @@ static CORD compile_str_method(env_t *env, ast_t *ast)
|
||||
static CORD compile_compare_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, EnumDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
if (!has_extra_data(def->tags)) {
|
||||
// Comparisons are simpler if there is only a tag, no tagged data:
|
||||
return CORD_all("static int ", full_name, "$compare(const ", full_name, "_t *x, const ", full_name,
|
||||
@ -88,7 +88,7 @@ static CORD compile_compare_method(env_t *env, ast_t *ast)
|
||||
static CORD compile_equals_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, EnumDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
if (!has_extra_data(def->tags)) {
|
||||
// Equality is simpler if there is only a tag, no tagged data:
|
||||
return CORD_all("static bool ", full_name, "$equal(const ", full_name, "_t *x, const ", full_name,
|
||||
@ -118,7 +118,7 @@ static CORD compile_equals_method(env_t *env, ast_t *ast)
|
||||
static CORD compile_hash_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, EnumDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
if (!has_extra_data(def->tags)) {
|
||||
// Hashing is simpler if there is only a tag, no tagged data:
|
||||
return CORD_all("static uint32_t ", full_name, "$hash(const ", full_name, "_t *obj, const TypeInfo *info) {\n"
|
||||
@ -152,7 +152,7 @@ static CORD compile_hash_method(env_t *env, ast_t *ast)
|
||||
void compile_enum_def(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, EnumDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
||||
compile_struct_def(env, WrapAST(ast, StructDef, .name=CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)), .fields=tag->fields));
|
||||
if (tag->fields) { // Constructor macros:
|
||||
@ -203,7 +203,7 @@ void compile_enum_def(env_t *env, ast_t *ast)
|
||||
CORD compile_enum_header(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, EnumDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
CORD header = CORD_all("typedef struct ", full_name, "_s ", full_name, "_t;\n",
|
||||
"extern const TypeInfo ", full_name, ";\n");
|
||||
CORD enum_def = CORD_all("struct ", full_name, "_s {\n"
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
type_t *TEXT_TYPE = NULL;
|
||||
|
||||
env_t *new_compilation_unit(void)
|
||||
env_t *new_compilation_unit(CORD *libname)
|
||||
{
|
||||
env_t *env = new(env_t);
|
||||
env->code = new(compilation_unit_t);
|
||||
@ -19,6 +19,7 @@ env_t *new_compilation_unit(void)
|
||||
env->globals = new(table_t);
|
||||
env->locals = new(table_t, .fallback=env->globals);
|
||||
env->imports = new(table_t);
|
||||
env->libname = libname;
|
||||
|
||||
if (!TEXT_TYPE)
|
||||
TEXT_TYPE = Type(TextType, .env=namespace_env(env, "Text"));
|
||||
@ -235,11 +236,13 @@ env_t *new_compilation_unit(void)
|
||||
return env;
|
||||
}
|
||||
|
||||
CORD namespace_prefix(namespace_t *ns)
|
||||
CORD namespace_prefix(CORD *libname, namespace_t *ns)
|
||||
{
|
||||
CORD prefix = CORD_EMPTY;
|
||||
for (; ns; ns = ns->parent)
|
||||
prefix = CORD_all(ns->name, "$", prefix);
|
||||
if (libname && *libname)
|
||||
prefix = CORD_all(*libname, "$", prefix);
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@ -250,7 +253,7 @@ env_t *load_module_env(env_t *env, ast_t *ast)
|
||||
if (cached) return cached;
|
||||
env_t *module_env = fresh_scope(env);
|
||||
module_env->code = new(compilation_unit_t);
|
||||
module_env->namespace = new(namespace_t, .name=name, .parent=env->namespace),
|
||||
module_env->namespace = new(namespace_t, .name=name);
|
||||
Table$str_set(module_env->imports, name, module_env);
|
||||
|
||||
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next)
|
||||
|
@ -37,6 +37,7 @@ typedef struct env_s {
|
||||
compilation_unit_t *code;
|
||||
fn_ctx_t *fn_ctx;
|
||||
loop_ctx_t *loop_ctx;
|
||||
CORD *libname; // Pointer to currently compiling library name (if any)
|
||||
namespace_t *namespace;
|
||||
const char *comprehension_var;
|
||||
} env_t;
|
||||
@ -49,9 +50,9 @@ typedef struct {
|
||||
};
|
||||
} binding_t;
|
||||
|
||||
env_t *new_compilation_unit(void);
|
||||
env_t *new_compilation_unit(CORD *libname);
|
||||
env_t *load_module_env(env_t *env, ast_t *ast);
|
||||
CORD namespace_prefix(namespace_t *ns);
|
||||
CORD namespace_prefix(CORD *libname, namespace_t *ns);
|
||||
env_t *global_scope(env_t *env);
|
||||
env_t *fresh_scope(env_t *env);
|
||||
env_t *for_scope(env_t *env, ast_t *ast);
|
||||
|
2
repl.c
2
repl.c
@ -28,7 +28,7 @@ static void eval(env_t *env, ast_t *ast, void *dest);
|
||||
|
||||
void repl(void)
|
||||
{
|
||||
env_t *env = new_compilation_unit();
|
||||
env_t *env = new_compilation_unit(NULL);
|
||||
void *dl = dlopen("libtomo.so", RTLD_LAZY);
|
||||
if (!dl) errx(1, "I couldn't find libtomo.so in your library paths");
|
||||
|
||||
|
12
structs.c
12
structs.c
@ -14,7 +14,7 @@
|
||||
static CORD compile_str_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, StructDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
const char *name = def->name;
|
||||
const char *dollar = strrchr(name, '$');
|
||||
if (dollar) name = dollar + 1;
|
||||
@ -39,7 +39,7 @@ static CORD compile_str_method(env_t *env, ast_t *ast)
|
||||
static CORD compile_compare_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, StructDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
CORD cmp_func = CORD_all("static int ", full_name, "$compare(const ", full_name, "_t *x, const ", full_name,
|
||||
"_t *y, const TypeInfo *info) {\n"
|
||||
"(void)info;\n",
|
||||
@ -67,7 +67,7 @@ static CORD compile_compare_method(env_t *env, ast_t *ast)
|
||||
static CORD compile_equals_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, StructDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
CORD eq_func = CORD_all("static bool ", full_name, "$equal(const ", full_name, "_t *x, const ", full_name,
|
||||
"_t *y, const TypeInfo *info) {\n"
|
||||
"(void)info;\n");
|
||||
@ -96,7 +96,7 @@ static CORD compile_equals_method(env_t *env, ast_t *ast)
|
||||
static CORD compile_hash_method(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, StructDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
CORD hash_func = CORD_all("static uint32_t ", full_name, "$hash(const ", full_name, "_t *obj, const TypeInfo *info) {\n"
|
||||
"(void)info;\n"
|
||||
"uint32_t field_hashes[] = {");
|
||||
@ -114,7 +114,7 @@ static CORD compile_hash_method(env_t *env, ast_t *ast)
|
||||
void compile_struct_def(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, StructDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
|
||||
type_t *t = Table$str_get(*env->types, def->name);
|
||||
assert(t && t->tag == StructType);
|
||||
@ -165,7 +165,7 @@ void compile_struct_def(env_t *env, ast_t *ast)
|
||||
CORD compile_struct_header(env_t *env, ast_t *ast)
|
||||
{
|
||||
auto def = Match(ast, StructDef);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->namespace), def->name);
|
||||
CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name);
|
||||
CORD header = CORD_all("typedef struct ", full_name, "_s ", full_name, "_t;\n");
|
||||
|
||||
CORD struct_code = CORD_all("struct ", full_name, "_s {\n");
|
||||
|
34
tomo.c
34
tomo.c
@ -120,7 +120,8 @@ int main(int argc, char *argv[])
|
||||
cc = ENV_CORD("CC");
|
||||
if (!cc) cc = "cc";
|
||||
|
||||
env_t *env = new_compilation_unit();
|
||||
CORD compilation_library_name = CORD_EMPTY;
|
||||
env_t *env = new_compilation_unit(&compilation_library_name);
|
||||
table_t dependency_files = {};
|
||||
table_t to_link = {};
|
||||
|
||||
@ -187,34 +188,7 @@ int main(int argc, char *argv[])
|
||||
if (!isalnum(*p) && *p != '_' && *p != '$')
|
||||
*p = '_';
|
||||
}
|
||||
|
||||
// Each type's namespace now exists within the library's namespace, on top of whatever
|
||||
// other namespace it was already in:
|
||||
namespace_t *lib_ns = new(namespace_t, .name=libname_id);
|
||||
for (int64_t i = 1; i <= Table$length(*env->types); i++) {
|
||||
struct {const char *name; type_t *type; } *entry = Table$entry(*env->types, i);
|
||||
env_t *type_env = NULL;
|
||||
switch (entry->type->tag) {
|
||||
case TextType: type_env = Match(entry->type, TextType)->env; break;
|
||||
case StructType: type_env = Match(entry->type, StructType)->env; break;
|
||||
case EnumType: type_env = Match(entry->type, EnumType)->env; break;
|
||||
case TypeInfoType: type_env = Match(entry->type, TypeInfoType)->env; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (type_env) {
|
||||
// Find the topmost namespace, and if it's not already `lib_ns`, then
|
||||
// set it to that:
|
||||
for (namespace_t **ns = &type_env->namespace; ; ns = &((*ns)->parent)) {
|
||||
if (*ns == lib_ns) {
|
||||
break;
|
||||
} else if (*ns == NULL) {
|
||||
*ns = lib_ns;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
compilation_library_name = libname_id;
|
||||
|
||||
// Build a "libwhatever.h" header that loads all the headers:
|
||||
const char *h_filename = heap_strf("lib%s.h", libname);
|
||||
@ -226,7 +200,7 @@ int main(int argc, char *argv[])
|
||||
if (!f) errx(1, "No such file: %s", filename);
|
||||
ast_t *ast = parse_file(f, NULL);
|
||||
if (!ast) errx(1, "Could not parse %s", f);
|
||||
env->namespace = new(namespace_t, .name=file_base_name(filename), .parent=lib_ns);
|
||||
env->namespace = new(namespace_t, .name=file_base_name(filename));
|
||||
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
|
||||
if (stmt->ast->tag == Import || (stmt->ast->tag == Declare && Match(stmt->ast, Declare)->value->tag == Import))
|
||||
continue;
|
||||
|
23
typecheck.c
23
typecheck.c
@ -137,7 +137,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
|
||||
if (!isalnum(*c) && *c != '_')
|
||||
*c = '_';
|
||||
}
|
||||
module_env->namespace = new(namespace_t, .name=libname_id);
|
||||
module_env->libname = (const char**)&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"));
|
||||
@ -156,7 +156,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
|
||||
if (!isalnum(*p) && *p != '_' && *p != '$')
|
||||
*p = '_';
|
||||
}
|
||||
module_file_env->namespace = new(namespace_t, .name=file_prefix, .parent=module_env->namespace);
|
||||
module_file_env->namespace = new(namespace_t, .name=file_prefix);
|
||||
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++) {
|
||||
@ -188,7 +188,7 @@ void prebind_statement(env_t *env, ast_t *statement)
|
||||
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(namespace_prefix(env->namespace), def->name)));
|
||||
.code=CORD_all(namespace_prefix(env->libname, 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;
|
||||
@ -201,7 +201,8 @@ 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(namespace_prefix(env->namespace), 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->libname, 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;
|
||||
@ -214,7 +215,8 @@ 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(namespace_prefix(env->namespace), 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->libname, 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;
|
||||
@ -240,7 +242,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
else
|
||||
bind_statement(env, decl->value);
|
||||
type_t *type = get_type(env, decl->value);
|
||||
CORD prefix = namespace_prefix(env->namespace);
|
||||
CORD prefix = namespace_prefix(env->libname, env->namespace);
|
||||
CORD code = CORD_cat(prefix ? prefix : "$", name);
|
||||
set_binding(env, name, new(binding_t, .type=type, .code=code));
|
||||
break;
|
||||
@ -251,8 +253,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
if (get_binding(env, name))
|
||||
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(namespace_prefix(env->namespace), name);
|
||||
CORD code = CORD_all(namespace_prefix(env->libname, env->namespace), name);
|
||||
set_binding(env, name, new(binding_t, .type=type, .code=code));
|
||||
break;
|
||||
}
|
||||
@ -318,9 +319,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(namespace_prefix(env->namespace), def->name, "$tagged$", tag->name)));
|
||||
set_binding(ns_env, tag->name, new(binding_t, .type=constructor_t, .code=CORD_all(namespace_prefix(env->libname, env->namespace), def->name, "$tagged$", tag->name)));
|
||||
} else { // Empty singleton value:
|
||||
CORD code = CORD_all("(", namespace_prefix(env->namespace), def->name, "_t){", namespace_prefix(env->namespace), def->name, "$tag$", tag->name, "}");
|
||||
CORD code = CORD_all("(", namespace_prefix(env->libname, env->namespace), def->name, "_t){", namespace_prefix(env->libname, 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);
|
||||
@ -339,7 +340,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("(", namespace_prefix(env->namespace), def->name, "_t)")));
|
||||
.code=CORD_all("(", namespace_prefix(env->libname, 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)"));
|
||||
|
Loading…
Reference in New Issue
Block a user