Pull namespaces from the type binding
This commit is contained in:
parent
f142b4ae53
commit
4592e95fa9
12
compile.c
12
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");
|
type_t *text_t = Table_str_get(*env->types, lang ? lang : "Text");
|
||||||
if (!text_t || text_t->tag != TextType)
|
if (!text_t || text_t->tag != TextType)
|
||||||
code_err(ast, "%s is not a valid text language name", lang);
|
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;
|
ast_list_t *chunks = Match(ast, TextJoin)->children;
|
||||||
if (!chunks) {
|
if (!chunks) {
|
||||||
return "(CORD)CORD_EMPTY";
|
return "(CORD)CORD_EMPTY";
|
||||||
@ -1108,11 +1108,11 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
chunk_code = compile(env, chunk->ast);
|
chunk_code = compile(env, chunk->ast);
|
||||||
} else if (chunk_t->tag == TextType && streq(Match(chunk_t, TextType)->lang, lang)) {
|
} else if (chunk_t->tag == TextType && streq(Match(chunk_t, TextType)->lang, lang)) {
|
||||||
chunk_code = compile(env, chunk->ast);
|
chunk_code = compile(env, chunk->ast);
|
||||||
} else if (lang && lang_ns) {
|
} else if (lang && lang_env) {
|
||||||
// Get conversion function:
|
// Get conversion function:
|
||||||
chunk_code = compile(env, chunk->ast);
|
chunk_code = compile(env, chunk->ast);
|
||||||
for (int64_t i = 1; i <= Table_length(*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_ns, i);
|
struct {const char *name; binding_t *b; } *entry = Table_entry(*lang_env->locals, i);
|
||||||
if (entry->b->type->tag != FunctionType) continue;
|
if (entry->b->type->tag != FunctionType) continue;
|
||||||
if (!(streq(entry->name, "escape") || strncmp(entry->name, "escape_", strlen("escape_")) == 0))
|
if (!(streq(entry->name, "escape") || strncmp(entry->name, "escape_", strlen("escape_")) == 0))
|
||||||
continue;
|
continue;
|
||||||
@ -1574,9 +1574,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
switch (value_t->tag) {
|
switch (value_t->tag) {
|
||||||
case TypeInfoType: {
|
case TypeInfoType: {
|
||||||
auto info = Match(value_t, TypeInfoType);
|
auto info = Match(value_t, TypeInfoType);
|
||||||
table_t *namespace = Table_str_get(*env->type_namespaces, info->name);
|
binding_t *b = get_binding(info->env, f->field);
|
||||||
if (!namespace) code_err(f->fielded, "I couldn't find a namespace for this type");
|
|
||||||
binding_t *b = Table_str_get(*namespace, f->field);
|
|
||||||
if (!b) code_err(ast, "I couldn't find the field '%s' on this type", 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");
|
if (!b->code) code_err(ast, "I couldn't figure out how to compile this field");
|
||||||
return b->code;
|
return b->code;
|
||||||
|
@ -14,7 +14,6 @@ env_t *new_compilation_unit(void)
|
|||||||
env_t *env = new(env_t);
|
env_t *env = new(env_t);
|
||||||
env->code = new(compilation_unit_t);
|
env->code = new(compilation_unit_t);
|
||||||
env->types = new(table_t);
|
env->types = new(table_t);
|
||||||
env->type_namespaces = new(table_t);
|
|
||||||
env->globals = new(table_t);
|
env->globals = new(table_t);
|
||||||
env->locals = new(table_t, .fallback=env->globals);
|
env->locals = new(table_t, .fallback=env->globals);
|
||||||
env->imports = new(table_t);
|
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++) {
|
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->globals, global_types[i].name, binding);
|
||||||
Table_str_set(env->types, global_types[i].name, global_types[i].type);
|
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++) {
|
for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
|
||||||
table_t *namespace = new(table_t, .fallback=env->globals);
|
binding_t *type_binding = Table_str_get(*env->globals, global_types[i].name);
|
||||||
Table_str_set(env->type_namespaces, global_types[i].name, namespace);
|
assert(type_binding);
|
||||||
env_t *ns_env = namespace_env(env, global_types[i].name);
|
env_t *ns_env = Match(type_binding->type, TypeInfoType)->env;
|
||||||
$ARRAY_FOREACH(global_types[i].namespace, j, ns_entry_t, entry, {
|
$ARRAY_FOREACH(global_types[i].namespace, j, ns_entry_t, entry, {
|
||||||
type_t *type = parse_type_string(ns_env, entry.type_str);
|
type_t *type = parse_type_string(ns_env, entry.type_str);
|
||||||
if (type->tag == ClosureType) type = Match(type, ClosureType)->fn;
|
if (type->tag == ClosureType) type = Match(type, ClosureType)->fn;
|
||||||
binding_t *b = new(binding_t, .code=entry.code, .type=type);
|
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)
|
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);
|
env_t *ns_env = new(env_t);
|
||||||
*ns_env = *env;
|
*ns_env = *env;
|
||||||
ns_env->locals = Table_str_get(*env->type_namespaces, namespace_name);
|
ns_env->locals = new(table_t, .fallback=env->globals);
|
||||||
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->scope_prefix = CORD_all(env->file_prefix, namespace_name, "$");
|
ns_env->scope_prefix = CORD_all(env->file_prefix, namespace_name, "$");
|
||||||
return ns_env;
|
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");
|
errx(1, "Table methods not implemented");
|
||||||
}
|
}
|
||||||
case BoolType: case IntType: case NumType: case TextType: {
|
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)));
|
binding_t *b = get_binding(env, CORD_to_const_char_star(type_to_cord(cls_type)));
|
||||||
if (!ns) {
|
assert(b);
|
||||||
code_err(self, "No namespace found for this type!");
|
return get_binding(Match(b->type, TypeInfoType)->env, name);
|
||||||
}
|
|
||||||
return Table_str_get(*ns, name);
|
|
||||||
}
|
}
|
||||||
case TypeInfoType: case StructType: case EnumType: {
|
case TypeInfoType: case StructType: case EnumType: {
|
||||||
const char *type_name;
|
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");
|
default: errx(1, "Unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
table_t *namespace = Table_str_get(*env->type_namespaces, type_name);
|
binding_t *b = get_binding(env, type_name);
|
||||||
if (!namespace) return NULL;
|
assert(b);
|
||||||
return Table_str_get(*namespace, name);
|
return get_binding(Match(b->type, TypeInfoType)->env, name);
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,9 @@ typedef struct loop_ctx_s {
|
|||||||
CORD skip_label, stop_label;
|
CORD skip_label, stop_label;
|
||||||
} loop_ctx_t;
|
} loop_ctx_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct env_s {
|
||||||
table_t *types, *globals, *locals;
|
table_t *types, *globals, *locals;
|
||||||
table_t *imports; // Map of 'use' name -> env_t*
|
table_t *imports; // Map of 'use' name -> env_t*
|
||||||
table_t *type_namespaces; // Map of type name -> namespace table
|
|
||||||
compilation_unit_t *code;
|
compilation_unit_t *code;
|
||||||
fn_ctx_t *fn_ctx;
|
fn_ctx_t *fn_ctx;
|
||||||
loop_ctx_t *loop_ctx;
|
loop_ctx_t *loop_ctx;
|
||||||
|
20
typecheck.c
20
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.fields = fields; // populate placeholder
|
||||||
type->__data.StructType.opaque = false;
|
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) {
|
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
|
||||||
bind_statement(ns_env, stmt->ast);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case EnumDef: {
|
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);
|
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));
|
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) {
|
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
|
||||||
bind_statement(ns_env, stmt->ast);
|
bind_statement(ns_env, stmt->ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LangDef: {
|
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),
|
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=Type(TextType)), .ret=type),
|
||||||
.code="(Text_t)"));
|
.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)
|
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
||||||
bind_statement(ns_env, stmt->ast);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case Use: {
|
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));
|
return get_type(module_env, WrapAST(ast, Var, access->field));
|
||||||
} else if (fielded_t->tag == TypeInfoType) {
|
} else if (fielded_t->tag == TypeInfoType) {
|
||||||
auto info = Match(fielded_t, TypeInfoType);
|
auto info = Match(fielded_t, TypeInfoType);
|
||||||
table_t *namespace = Table_str_get(*env->type_namespaces, info->name);
|
assert(info->env);
|
||||||
if (!namespace) code_err(access->fielded, "I couldn't find a namespace for this type");
|
binding_t *b = get_binding(info->env, access->field);
|
||||||
binding_t *b = Table_str_get(*namespace, access->field);
|
|
||||||
if (!b) code_err(ast, "I couldn't find the field '%s' on this type", access->field);
|
if (!b) code_err(ast, "I couldn't find the field '%s' on this type", access->field);
|
||||||
return b->type;
|
return b->type;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user