From 4592e95fa937e5e8ef8343053b9d5accb2aa5d56 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Thu, 21 Mar 2024 13:33:10 -0400 Subject: [PATCH] Pull namespaces from the type binding --- compile.c | 12 +++++------- environment.c | 36 +++++++++++++++++------------------- environment.h | 3 +-- typecheck.c | 20 +++++++++----------- types.h | 1 + 5 files changed, 33 insertions(+), 39 deletions(-) diff --git a/compile.c b/compile.c index 5d2d754..7dfe0dc 100644 --- a/compile.c +++ b/compile.c @@ -1093,7 +1093,7 @@ CORD compile(env_t *env, ast_t *ast) type_t *text_t = Table_str_get(*env->types, lang ? lang : "Text"); if (!text_t || text_t->tag != TextType) code_err(ast, "%s is not a valid text language name", lang); - table_t *lang_ns = lang ? Table_str_get(*env->type_namespaces, lang) : NULL; + env_t *lang_env = lang ? Match(get_binding(env, lang)->type, TypeInfoType)->env : NULL; ast_list_t *chunks = Match(ast, TextJoin)->children; if (!chunks) { return "(CORD)CORD_EMPTY"; @@ -1108,11 +1108,11 @@ CORD compile(env_t *env, ast_t *ast) chunk_code = compile(env, chunk->ast); } else if (chunk_t->tag == TextType && streq(Match(chunk_t, TextType)->lang, lang)) { chunk_code = compile(env, chunk->ast); - } else if (lang && lang_ns) { + } else if (lang && lang_env) { // Get conversion function: chunk_code = compile(env, chunk->ast); - for (int64_t i = 1; i <= Table_length(*lang_ns); i++) { - struct {const char *name; binding_t *b; } *entry = Table_entry(*lang_ns, i); + for (int64_t i = 1; i <= Table_length(*lang_env->locals); i++) { + struct {const char *name; binding_t *b; } *entry = Table_entry(*lang_env->locals, i); if (entry->b->type->tag != FunctionType) continue; if (!(streq(entry->name, "escape") || strncmp(entry->name, "escape_", strlen("escape_")) == 0)) continue; @@ -1574,9 +1574,7 @@ CORD compile(env_t *env, ast_t *ast) switch (value_t->tag) { case TypeInfoType: { auto info = Match(value_t, TypeInfoType); - table_t *namespace = Table_str_get(*env->type_namespaces, info->name); - if (!namespace) code_err(f->fielded, "I couldn't find a namespace for this type"); - binding_t *b = Table_str_get(*namespace, f->field); + binding_t *b = get_binding(info->env, f->field); if (!b) code_err(ast, "I couldn't find the field '%s' on this type", f->field); if (!b->code) code_err(ast, "I couldn't figure out how to compile this field"); return b->code; diff --git a/environment.c b/environment.c index af875e8..3d463c4 100644 --- a/environment.c +++ b/environment.c @@ -14,7 +14,6 @@ env_t *new_compilation_unit(void) env_t *env = new(env_t); env->code = new(compilation_unit_t); env->types = new(table_t); - env->type_namespaces = new(table_t); env->globals = new(table_t); env->locals = new(table_t, .fallback=env->globals); env->imports = new(table_t); @@ -162,20 +161,21 @@ env_t *new_compilation_unit(void) }; for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) { - binding_t *binding = new(binding_t, .type=Type(TypeInfoType, .name=global_types[i].name, .type=global_types[i].type)); + env_t *ns_env = namespace_env(env, global_types[i].name); + binding_t *binding = new(binding_t, .type=Type(TypeInfoType, .name=global_types[i].name, .type=global_types[i].type, .env=ns_env)); Table_str_set(env->globals, global_types[i].name, binding); Table_str_set(env->types, global_types[i].name, global_types[i].type); } for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) { - table_t *namespace = new(table_t, .fallback=env->globals); - Table_str_set(env->type_namespaces, global_types[i].name, namespace); - env_t *ns_env = namespace_env(env, global_types[i].name); + binding_t *type_binding = Table_str_get(*env->globals, global_types[i].name); + assert(type_binding); + env_t *ns_env = Match(type_binding->type, TypeInfoType)->env; $ARRAY_FOREACH(global_types[i].namespace, j, ns_entry_t, entry, { type_t *type = parse_type_string(ns_env, entry.type_str); if (type->tag == ClosureType) type = Match(type, ClosureType)->fn; binding_t *b = new(binding_t, .code=entry.code, .type=type); - Table_str_set(namespace, entry.name, b); + set_binding(ns_env, entry.name, b); }, {}) } @@ -250,13 +250,13 @@ env_t *for_scope(env_t *env, ast_t *ast) env_t *namespace_env(env_t *env, const char *namespace_name) { + binding_t *b = get_binding(env, namespace_name); + if (b) + return Match(b->type, TypeInfoType)->env; + env_t *ns_env = new(env_t); *ns_env = *env; - ns_env->locals = Table_str_get(*env->type_namespaces, namespace_name); - if (!ns_env->locals) { - ns_env->locals = new(table_t, .fallback=env->globals); - Table_str_set(env->type_namespaces, namespace_name, ns_env->locals); - } + ns_env->locals = new(table_t, .fallback=env->globals); ns_env->scope_prefix = CORD_all(env->file_prefix, namespace_name, "$"); return ns_env; } @@ -288,11 +288,9 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name) errx(1, "Table methods not implemented"); } case BoolType: case IntType: case NumType: case TextType: { - table_t *ns = Table_str_get(*env->type_namespaces, CORD_to_const_char_star(type_to_cord(cls_type))); - if (!ns) { - code_err(self, "No namespace found for this type!"); - } - return Table_str_get(*ns, name); + binding_t *b = get_binding(env, CORD_to_const_char_star(type_to_cord(cls_type))); + assert(b); + return get_binding(Match(b->type, TypeInfoType)->env, name); } case TypeInfoType: case StructType: case EnumType: { const char *type_name; @@ -303,9 +301,9 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name) default: errx(1, "Unreachable"); } - table_t *namespace = Table_str_get(*env->type_namespaces, type_name); - if (!namespace) return NULL; - return Table_str_get(*namespace, name); + binding_t *b = get_binding(env, type_name); + assert(b); + return get_binding(Match(b->type, TypeInfoType)->env, name); } default: break; } diff --git a/environment.h b/environment.h index 43f6b0f..40ddb8e 100644 --- a/environment.h +++ b/environment.h @@ -31,10 +31,9 @@ typedef struct loop_ctx_s { CORD skip_label, stop_label; } loop_ctx_t; -typedef struct { +typedef struct env_s { table_t *types, *globals, *locals; table_t *imports; // Map of 'use' name -> env_t* - table_t *type_namespaces; // Map of type name -> namespace table compilation_unit_t *code; fn_ctx_t *fn_ctx; loop_ctx_t *loop_ctx; diff --git a/typecheck.c b/typecheck.c index 00e7c66..30ac451 100644 --- a/typecheck.c +++ b/typecheck.c @@ -132,12 +132,12 @@ void bind_statement(env_t *env, ast_t *statement) type->__data.StructType.fields = fields; // populate placeholder type->__data.StructType.opaque = false; + type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); + Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name))); + for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) { bind_statement(ns_env, stmt->ast); } - - type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type); - Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name))); break; } case EnumDef: { @@ -175,13 +175,12 @@ void bind_statement(env_t *env, ast_t *statement) Table_str_set(env->types, heap_strf("%s$%s", def->name, tag->name), tag->type); } - type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type); + type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type)); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) { bind_statement(ns_env, stmt->ast); } - break; } case LangDef: { @@ -198,11 +197,11 @@ void bind_statement(env_t *env, ast_t *statement) new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=Type(TextType)), .ret=type), .code="(Text_t)")); + type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); + Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type)); + for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) bind_statement(ns_env, stmt->ast); - - type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type); - Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type)); break; } case Use: { @@ -427,9 +426,8 @@ type_t *get_type(env_t *env, ast_t *ast) return get_type(module_env, WrapAST(ast, Var, access->field)); } else if (fielded_t->tag == TypeInfoType) { auto info = Match(fielded_t, TypeInfoType); - table_t *namespace = Table_str_get(*env->type_namespaces, info->name); - if (!namespace) code_err(access->fielded, "I couldn't find a namespace for this type"); - binding_t *b = Table_str_get(*namespace, access->field); + assert(info->env); + binding_t *b = get_binding(info->env, access->field); if (!b) code_err(ast, "I couldn't find the field '%s' on this type", access->field); return b->type; } diff --git a/types.h b/types.h index 17c778f..83d8ca6 100644 --- a/types.h +++ b/types.h @@ -98,6 +98,7 @@ struct type_s { struct { const char *name; type_t *type; + struct env_s *env; } TypeInfoType; struct { const char *name;