aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c29
-rw-r--r--environment.c43
-rw-r--r--environment.h1
-rw-r--r--typecheck.c20
-rw-r--r--types.h3
5 files changed, 63 insertions, 33 deletions
diff --git a/compile.c b/compile.c
index 7dfe0dc1..82c302d8 100644
--- a/compile.c
+++ b/compile.c
@@ -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);
diff --git a/types.h b/types.h
index 83d8ca6a..df913de5 100644
--- a/types.h
+++ b/types.h
@@ -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;