diff options
| -rw-r--r-- | compile.c | 14 | ||||
| -rw-r--r-- | typecheck.c | 44 |
2 files changed, 26 insertions, 32 deletions
@@ -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); |
