diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-03-22 01:52:00 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-03-22 01:52:00 -0400 |
| commit | f21fc700bb5e37a653142b0ecd142f1ae3132c5c (patch) | |
| tree | 2609e8c0f42fb8ac2f5b53f0fac4480c65ef62ee | |
| parent | 73c0c6b5404137f6db269153a8236748f1dc5de5 (diff) | |
Handle type namespaces in other modules
| -rw-r--r-- | compile.c | 29 | ||||
| -rw-r--r-- | environment.c | 43 | ||||
| -rw-r--r-- | environment.h | 1 | ||||
| -rw-r--r-- | typecheck.c | 20 | ||||
| -rw-r--r-- | types.h | 3 |
5 files changed, 63 insertions, 33 deletions
@@ -82,8 +82,8 @@ CORD compile_type(env_t *env, type_t *t) case IntType: return Match(t, IntType)->bits == 64 ? "Int_t" : CORD_asprintf("Int%ld_t", Match(t, IntType)->bits); case NumType: return Match(t, NumType)->bits == 64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits); case TextType: { - const char *dsl = Match(t, TextType)->lang; - return dsl ? CORD_all(env->file_prefix, dsl, "_t") : "Text_t"; + auto text = Match(t, TextType); + return text->lang ? CORD_all(text->env->file_prefix, text->lang, "_t") : "Text_t"; } case ArrayType: return "array_t"; case TableType: return "table_t"; @@ -98,8 +98,14 @@ CORD compile_type(env_t *env, type_t *t) } case ClosureType: return "closure_t"; case PointerType: return CORD_cat(compile_type(env, Match(t, PointerType)->pointed), "*"); - case StructType: return CORD_all(env->file_prefix, Match(t, StructType)->name, "_t"); - case EnumType: return CORD_all(env->file_prefix, Match(t, EnumType)->name, "_t"); + case StructType: { + auto s = Match(t, StructType); + return CORD_all(s->env->file_prefix, s->name, "_t"); + } + case EnumType: { + auto e = Match(t, EnumType); + return CORD_all(e->env->file_prefix, e->name, "_t"); + } case TypeInfoType: return "TypeInfo"; default: compiler_err(NULL, NULL, NULL, "Not implemented"); } @@ -1735,9 +1741,18 @@ CORD compile_type_info(env_t *env, type_t *t) { switch (t->tag) { case BoolType: case IntType: case NumType: return CORD_asprintf("&%r", type_to_cord(t)); - case TextType: return Match(t, TextType)->lang ? CORD_all("(&", env->file_prefix, Match(t, TextType)->lang, ")") : "&Text"; - case StructType: return CORD_all("(&", env->file_prefix, Match(t, StructType)->name, ")"); - case EnumType: return CORD_all("(&", env->file_prefix, Match(t, EnumType)->name, ")"); + case TextType: { + auto text = Match(t, TextType); + return text->lang ? CORD_all("(&", text->env->file_prefix, text->lang, ")") : "&Text"; + } + case StructType: { + auto s = Match(t, StructType); + return CORD_all("(&", s->env->file_prefix, s->name, ")"); + } + case EnumType: { + auto e = Match(t, EnumType); + return CORD_all("(&", e->env->file_prefix, e->name, ")"); + } case ArrayType: { type_t *item_t = Match(t, ArrayType)->item_type; return CORD_asprintf("$ArrayInfo(%r)", compile_type_info(env, item_t)); diff --git a/environment.c b/environment.c index 3d463c42..806bc019 100644 --- a/environment.c +++ b/environment.c @@ -9,6 +9,8 @@ #include "typecheck.h" #include "builtins/util.h" +type_t *TEXT_TYPE = NULL; + env_t *new_compilation_unit(void) { env_t *env = new(env_t); @@ -18,12 +20,15 @@ env_t *new_compilation_unit(void) env->locals = new(table_t, .fallback=env->globals); env->imports = new(table_t); + if (!TEXT_TYPE) + TEXT_TYPE = Type(TextType, .env=namespace_env(env, "Text")); + struct { const char *name; binding_t binding; } global_vars[] = { - {"say", {.code="say", .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=Type(TextType)), .ret=Type(VoidType))}}, - {"fail", {.code="fail", .type=Type(FunctionType, .args=new(arg_t, .name="message", .type=Type(TextType)), .ret=Type(AbortType))}}, + {"say", {.code="say", .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=Type(VoidType))}}, + {"fail", {.code="fail", .type=Type(FunctionType, .args=new(arg_t, .name="message", .type=TEXT_TYPE), .ret=Type(AbortType))}}, {"USE_COLOR", {.code="USE_COLOR", .type=Type(BoolType)}}, }; @@ -137,7 +142,7 @@ env_t *new_compilation_unit(void) #undef F2 #undef F #undef C - {"Text", Type(TextType), "Text_t", "Text", $TypedArray(ns_entry_t, + {"Text", TEXT_TYPE, "Text_t", "Text", $TypedArray(ns_entry_t, {"quoted", "Text__quoted", "func(text:Text, color=no)->Text"}, {"upper", "Text__upper", "func(text:Text)->Text"}, {"lower", "Text__lower", "func(text:Text)->Text"}, @@ -161,7 +166,7 @@ env_t *new_compilation_unit(void) }; for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) { - env_t *ns_env = namespace_env(env, global_types[i].name); + env_t *ns_env = global_types[i].type == TEXT_TYPE ? Match(TEXT_TYPE, TextType)->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); @@ -287,23 +292,27 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name) case TableType: { errx(1, "Table methods not implemented"); } - case BoolType: case IntType: case NumType: case TextType: { + case BoolType: case IntType: case NumType: { 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; - switch (cls_type->tag) { - case TypeInfoType: type_name = Match(cls_type, TypeInfoType)->name; break; - case StructType: type_name = Match(cls_type, StructType)->name; break; - case EnumType: type_name = Match(cls_type, EnumType)->name; break; - default: errx(1, "Unreachable"); - } - - binding_t *b = get_binding(env, type_name); - assert(b); - return get_binding(Match(b->type, TypeInfoType)->env, name); + case TextType: { + auto text = Match(cls_type, TextType); + assert(text->env); + return get_binding(text->env, name); + } + case StructType: { + auto struct_ = Match(cls_type, StructType); + return struct_->env ? get_binding(struct_->env, name) : NULL; + } + case EnumType: { + auto enum_ = Match(cls_type, StructType); + return enum_->env ? get_binding(enum_->env, name) : NULL; + } + case TypeInfoType: { + auto info = Match(cls_type, TypeInfoType); + return info->env ? get_binding(info->env, name) : NULL; } default: break; } diff --git a/environment.h b/environment.h index 40ddb8ec..b1b91242 100644 --- a/environment.h +++ b/environment.h @@ -57,5 +57,6 @@ binding_t *get_binding(env_t *env, const char *name); void set_binding(env_t *env, const char *name, binding_t *binding); binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name); #define code_err(ast, ...) compiler_err((ast)->file, (ast)->start, (ast)->end, __VA_ARGS__) +extern type_t *TEXT_TYPE; // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/typecheck.c b/typecheck.c index 30ac451d..615abe74 100644 --- a/typecheck.c +++ b/typecheck.c @@ -119,7 +119,7 @@ void bind_statement(env_t *env, ast_t *statement) env_t *ns_env = namespace_env(env, def->name); arg_t *fields = NULL; - type_t *type = Type(StructType, .name=def->name, .fields=fields, .opaque=true); // placeholder + type_t *type = Type(StructType, .name=def->name, .fields=fields, .opaque=true, .env=ns_env); // placeholder Table_str_set(env->types, def->name, type); for (arg_ast_t *field_ast = def->fields; field_ast; field_ast = field_ast->next) { type_t *field_t = get_arg_ast_type(env, field_ast); @@ -146,7 +146,7 @@ void bind_statement(env_t *env, ast_t *statement) env_t *ns_env = namespace_env(env, def->name); tag_t *tags = NULL; - type_t *type = Type(EnumType, .name=def->name, .tags=tags, .opaque=true); // placeholder + type_t *type = Type(EnumType, .name=def->name, .tags=tags, .opaque=true, .env=ns_env); // placeholder Table_str_set(env->types, def->name, type); for (tag_ast_t *tag_ast = def->tags; tag_ast; tag_ast = tag_ast->next) { arg_t *fields = NULL; @@ -158,7 +158,8 @@ void bind_statement(env_t *env, ast_t *statement) fields = new(arg_t, .name=field_ast->name, .type=field_t, .default_val=field_ast->value, .next=fields); } REVERSE_LIST(fields); - type_t *tag_type = Type(StructType, .name=heap_strf("%s$%s", def->name, tag_ast->name), .fields=fields); + env_t *member_ns = namespace_env(env, heap_strf("%s$%s", def->name, tag_ast->name)); + type_t *tag_type = Type(StructType, .name=heap_strf("%s$%s", def->name, tag_ast->name), .fields=fields, .env=member_ns); tags = new(tag_t, .name=tag_ast->name, .tag_value=tag_ast->value, .type=tag_type, .next=tags); } REVERSE_LIST(tags); @@ -186,15 +187,15 @@ void bind_statement(env_t *env, ast_t *statement) case LangDef: { auto def = Match(statement, LangDef); - type_t *type = Type(TextType, .lang=def->name); - Table_str_set(env->types, def->name, type); 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(ns_env, "from_unsafe_text", - new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=Type(TextType)), .ret=type), + 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)"))); set_binding(ns_env, "text_content", - new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=Type(TextType)), .ret=type), + new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type), .code="(Text_t)")); type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); @@ -322,9 +323,10 @@ type_t *get_type(env_t *env, ast_t *ast) code_err(ast, "'&' stack references can only be used on variables or fields of variables"); } - case TextLiteral: return Type(TextType); + case TextLiteral: return TEXT_TYPE; case TextJoin: { - return Type(TextType, .lang=Match(ast, TextJoin)->lang); + const char *lang = Match(ast, TextJoin)->lang; + return lang ? Match(get_binding(env, lang)->type, TypeInfoType)->type : TEXT_TYPE; } case Var: { auto var = Match(ast, Var); @@ -67,6 +67,7 @@ struct type_s { } NumType; struct { const char *lang; + struct env_s *env; } TextType; struct { type_t *item_type; @@ -89,11 +90,13 @@ struct type_s { const char *name; arg_t *fields; bool opaque; + struct env_s *env; } StructType; struct { const char *name; tag_t *tags; bool opaque; + struct env_s *env; } EnumType; struct { const char *name; |
