aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-05-19 01:46:30 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-05-19 01:46:30 -0400
commitb0d1daa0f3abe5f9128064388adfffccd2608ca5 (patch)
treeca74a48ec2cdb68189e5e3e69eeb8a5d120e3237
parent4f2421aeeaa2fba490ca4d815be1414feb51c588 (diff)
Fix up some binding order issues and also some inline C issues with
heap_pop()
-rw-r--r--compile.c14
-rw-r--r--typecheck.c44
2 files changed, 26 insertions, 32 deletions
diff --git a/compile.c b/compile.c
index cd0c5eea..6c50890a 100644
--- a/compile.c
+++ b/compile.c
@@ -512,6 +512,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
if (fndef->cache && fndef->cache->tag == Int && Match(fndef->cache, Int)->i > 0) {
const char *arg_type_name = heap_strf("%s$args", CORD_to_const_char_star(name));
ast_t *args_def = FakeAST(StructDef, .name=arg_type_name, .fields=fndef->args);
+ prebind_statement(env, args_def);
bind_statement(env, args_def);
(void)compile_statement(env, args_def);
type_t *args_t = Table$str_get(*env->types, arg_type_name);
@@ -772,6 +773,8 @@ CORD compile_statement(env_t *env, ast_t *ast)
CORD code = "{\n";
env = fresh_scope(env);
+ for (ast_list_t *stmt = stmts; stmt; stmt = stmt->next)
+ prebind_statement(env, stmt->ast);
for (ast_list_t *stmt = stmts; stmt; stmt = stmt->next) {
bind_statement(env, stmt->ast);
code = CORD_all(code, compile_statement(env, stmt->ast), "\n");
@@ -931,7 +934,9 @@ env_t *with_enum_scope(env_t *env, type_t *t)
for (tag_t *tag = Match(t, EnumType)->tags; tag; tag = tag->next) {
if (get_binding(env, tag->name))
continue;
- set_binding(env, tag->name, get_binding(ns_env, tag->name));
+ binding_t *b = get_binding(ns_env, tag->name);
+ assert(b);
+ set_binding(env, tag->name, b);
}
return env;
}
@@ -1314,6 +1319,8 @@ CORD compile(env_t *env, ast_t *ast)
CORD code = "({\n";
env = fresh_scope(env);
+ for (ast_list_t *stmt = stmts; stmt; stmt = stmt->next)
+ prebind_statement(env, stmt->ast);
for (ast_list_t *stmt = stmts; stmt; stmt = stmt->next) {
bind_statement(env, stmt->ast);
if (stmt->next) {
@@ -1622,7 +1629,7 @@ CORD compile(env_t *env, ast_t *ast)
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=32));
- ast_t *default_cmp = FakeAST(InlineCCode, CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"));
+ ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), .type=NewTypeAST(NULL, NULL, NULL, FunctionTypeAST));
arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp));
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
return CORD_all("Array$heap_push_value(", self, ", ", arg_code, ", ", compile_type_info(env, self_value_t), ")");
@@ -1631,7 +1638,7 @@ CORD compile(env_t *env, ast_t *ast)
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=32));
- ast_t *default_cmp = FakeAST(InlineCCode, CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"));
+ ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), .type=NewTypeAST(NULL, NULL, NULL, FunctionTypeAST));
arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp);
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", compile_type_info(env, self_value_t), ", ", compile_type(env, item_t), ")");
@@ -1761,6 +1768,7 @@ CORD compile(env_t *env, ast_t *ast)
CORD condition = Match(Match(if_->condition, Declare)->var, Var)->name;
CORD decl = compile_statement(env, if_->condition);
env_t *true_scope = fresh_scope(env);
+ prebind_statement(true_scope, if_->condition);
bind_statement(true_scope, if_->condition);
type_t *true_type = get_type(true_scope, if_->body);
type_t *false_type = get_type(env, if_->else_body);
diff --git a/typecheck.c b/typecheck.c
index 8dd62c07..e3cf0b5c 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -151,9 +151,9 @@ void prebind_statement(env_t *env, ast_t *statement)
env_t *ns_env = namespace_env(env, def->name);
type_t *type = Type(StructType, .name=def->name, .opaque=true, .env=ns_env); // placeholder
Table$str_set(env->types, def->name, type);
- for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
+ set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .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)
prebind_statement(ns_env, stmt->ast);
- }
break;
}
case EnumDef: {
@@ -164,9 +164,9 @@ 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);
- for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
+ set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), .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)
prebind_statement(ns_env, stmt->ast);
- }
break;
}
case LangDef: {
@@ -177,6 +177,7 @@ 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(env->file_prefix, 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;
@@ -219,14 +220,11 @@ void bind_statement(env_t *env, ast_t *statement)
}
case StructDef: {
auto def = Match(statement, StructDef);
- if (get_binding(env, def->name))
- code_err(statement, "A %T called '%s' has already been defined", get_binding(env, def->name)->type, def->name);
-
env_t *ns_env = namespace_env(env, def->name);
-
+ type_t *type = Table$str_get(*env->types, def->name);
+ if (!type) code_err(statement, "Couldn't find type!");
+ assert(type);
arg_t *fields = NULL;
- 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);
if ((field_t->tag == StructType && Match(field_t, StructType)->opaque)
@@ -244,9 +242,6 @@ 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->locals, 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);
}
@@ -254,14 +249,10 @@ void bind_statement(env_t *env, ast_t *statement)
}
case EnumDef: {
auto def = Match(statement, EnumDef);
- if (get_binding(env, def->name))
- code_err(statement, "A %T called '%s' has already been defined", get_binding(env, def->name)->type, def->name);
-
env_t *ns_env = namespace_env(env, def->name);
-
+ type_t *type = Table$str_get(*env->types, def->name);
+ assert(type);
tag_t *tags = NULL;
- 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;
for (arg_ast_t *field_ast = tag_ast->fields; field_ast; field_ast = field_ast->next) {
@@ -296,9 +287,6 @@ 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, .env=ns_env);
- Table$str_set(env->locals, 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);
}
@@ -306,9 +294,6 @@ void bind_statement(env_t *env, ast_t *statement)
}
case LangDef: {
auto def = Match(statement, LangDef);
- if (get_binding(env, def->name))
- code_err(statement, "A %T called '%s' has already been defined", get_binding(env, def->name)->type, def->name);
-
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);
@@ -320,9 +305,6 @@ void bind_statement(env_t *env, ast_t *statement)
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);
- Table$str_set(env->locals, 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;
@@ -913,6 +895,7 @@ type_t *get_type(env_t *env, ast_t *ast)
for (when_clause_t *clause = when->clauses; clause; clause = clause->next) {
const char *tag_name = Match(clause->tag_name, Var)->name;
type_t *tag_type = NULL;
+ CORD valid_tags = CORD_EMPTY;
for (match_t *m = matches; m; m = m->next) {
if (streq(m->name, tag_name)) {
if (m->handled)
@@ -921,10 +904,13 @@ type_t *get_type(env_t *env, ast_t *ast)
tag_type = m->type;
break;
}
+ if (valid_tags) valid_tags = CORD_cat(valid_tags, ", ");
+ valid_tags = CORD_cat(valid_tags, m->name);
}
if (!tag_type)
- code_err(clause->tag_name, "This is not a valid tag for the type %T", subject_t);
+ code_err(clause->tag_name, "There is no tag '%s' for the type %T (valid tags: %s)",
+ tag_name, subject_t, CORD_to_char_star(valid_tags));
env_t *scope = env;
auto tag_struct = Match(tag_type, StructType);