diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.c | 318 | ||||
| -rw-r--r-- | src/ast.h | 3 | ||||
| -rw-r--r-- | src/compile/enums.c | 64 | ||||
| -rw-r--r-- | src/compile/enums.h | 6 | ||||
| -rw-r--r-- | src/compile/files.c | 25 | ||||
| -rw-r--r-- | src/compile/headers.c | 41 | ||||
| -rw-r--r-- | src/parse/typedefs.c | 4 | ||||
| -rw-r--r-- | src/parse/types.c | 4 | ||||
| -rw-r--r-- | src/typecheck.c | 2 |
9 files changed, 422 insertions, 45 deletions
@@ -446,3 +446,321 @@ CONSTFUNC ast_e binop_tag(ast_e tag) { default: return Unknown; } } + +static void ast_visit_list(ast_list_t *ast_list, void (*visitor)(ast_t *, void *), void *userdata) { + for (ast_list_t *ast = ast_list; ast; ast = ast->next) + ast_visit(ast->ast, visitor, userdata); +} + +static void ast_visit_args(arg_ast_t *args, void (*visitor)(ast_t *, void *), void *userdata) { + for (arg_ast_t *arg = args; arg; arg = arg->next) + ast_visit(arg->value, visitor, userdata); +} + +void ast_visit(ast_t *ast, void (*visitor)(ast_t *, void *), void *userdata) { + if (!ast) return; + visitor(ast, userdata); + + switch (ast->tag) { + case Unknown: + case None: + case Bool: + case Var: + case Int: + case Num: + case Path: + case TextLiteral: return; + case TextJoin: ast_visit_list(Match(ast, TextJoin)->children, visitor, userdata); return; + case Declare: { + DeclareMatch(decl, ast, Declare); + ast_visit(decl->var, visitor, userdata); + ast_visit(decl->value, visitor, userdata); + return; + } + case Assign: { + DeclareMatch(assign, ast, Assign); + ast_visit_list(assign->targets, visitor, userdata); + ast_visit_list(assign->values, visitor, userdata); + return; + } + case BINOP_CASES: { + binary_operands_t op = BINARY_OPERANDS(ast); + ast_visit(op.lhs, visitor, userdata); + ast_visit(op.rhs, visitor, userdata); + return; + } + case Negative: { + ast_visit(Match(ast, Negative)->value, visitor, userdata); + return; + } + case Not: { + ast_visit(Match(ast, Not)->value, visitor, userdata); + return; + } + case HeapAllocate: { + ast_visit(Match(ast, HeapAllocate)->value, visitor, userdata); + return; + } + case StackReference: { + ast_visit(Match(ast, StackReference)->value, visitor, userdata); + return; + } + case Min: { + DeclareMatch(min, ast, Min); + ast_visit(min->lhs, visitor, userdata); + ast_visit(min->key, visitor, userdata); + ast_visit(min->rhs, visitor, userdata); + return; + } + case Max: { + DeclareMatch(max, ast, Max); + ast_visit(max->lhs, visitor, userdata); + ast_visit(max->key, visitor, userdata); + ast_visit(max->rhs, visitor, userdata); + return; + } + case List: { + ast_visit_list(Match(ast, List)->items, visitor, userdata); + return; + } + case Set: { + ast_visit_list(Match(ast, Set)->items, visitor, userdata); + return; + } + case Table: { + DeclareMatch(table, ast, Table); + ast_visit_list(table->entries, visitor, userdata); + ast_visit(table->default_value, visitor, userdata); + ast_visit(table->fallback, visitor, userdata); + return; + } + case TableEntry: { + DeclareMatch(entry, ast, TableEntry); + ast_visit(entry->key, visitor, userdata); + ast_visit(entry->value, visitor, userdata); + return; + } + case Comprehension: { + DeclareMatch(comp, ast, Comprehension); + ast_visit(comp->expr, visitor, userdata); + ast_visit_list(comp->vars, visitor, userdata); + ast_visit(comp->iter, visitor, userdata); + ast_visit(comp->filter, visitor, userdata); + return; + } + case FunctionDef: { + DeclareMatch(def, ast, FunctionDef); + ast_visit(def->name, visitor, userdata); + ast_visit_args(def->args, visitor, userdata); + ast_visit(def->body, visitor, userdata); + return; + } + case ConvertDef: { + DeclareMatch(def, ast, ConvertDef); + ast_visit_args(def->args, visitor, userdata); + ast_visit(def->body, visitor, userdata); + return; + } + case Lambda: { + DeclareMatch(lambda, ast, Lambda); + ast_visit_args(lambda->args, visitor, userdata); + ast_visit(lambda->body, visitor, userdata); + return; + } + case FunctionCall: { + DeclareMatch(call, ast, FunctionCall); + ast_visit(call->fn, visitor, userdata); + ast_visit_args(call->args, visitor, userdata); + return; + } + case MethodCall: { + DeclareMatch(call, ast, MethodCall); + ast_visit(call->self, visitor, userdata); + ast_visit_args(call->args, visitor, userdata); + return; + } + case Block: { + ast_visit_list(Match(ast, Block)->statements, visitor, userdata); + return; + } + case For: { + DeclareMatch(for_, ast, For); + ast_visit_list(for_->vars, visitor, userdata); + ast_visit(for_->iter, visitor, userdata); + ast_visit(for_->body, visitor, userdata); + ast_visit(for_->empty, visitor, userdata); + return; + } + case While: { + DeclareMatch(while_, ast, While); + ast_visit(while_->condition, visitor, userdata); + ast_visit(while_->body, visitor, userdata); + return; + } + case Repeat: { + ast_visit(Match(ast, Repeat)->body, visitor, userdata); + return; + } + case If: { + DeclareMatch(if_, ast, If); + ast_visit(if_->condition, visitor, userdata); + ast_visit(if_->body, visitor, userdata); + ast_visit(if_->else_body, visitor, userdata); + return; + } + case When: { + DeclareMatch(when, ast, When); + ast_visit(when->subject, visitor, userdata); + for (when_clause_t *clause = when->clauses; clause; clause = clause->next) { + ast_visit(clause->pattern, visitor, userdata); + ast_visit(clause->body, visitor, userdata); + } + ast_visit(when->else_body, visitor, userdata); + return; + } + case Reduction: { + DeclareMatch(reduction, ast, Reduction); + ast_visit(reduction->key, visitor, userdata); + ast_visit(reduction->iter, visitor, userdata); + return; + } + case Skip: + case Stop: + case Pass: return; + case Defer: { + ast_visit(Match(ast, Defer)->body, visitor, userdata); + return; + } + case Return: { + ast_visit(Match(ast, Return)->value, visitor, userdata); + return; + } + case Extern: return; + case StructDef: { + DeclareMatch(def, ast, StructDef); + ast_visit_args(def->fields, visitor, userdata); + ast_visit(def->namespace, visitor, userdata); + return; + } + case EnumDef: { + DeclareMatch(def, ast, EnumDef); + for (tag_ast_t *tag = def->tags; tag; tag = tag->next) + ast_visit_args(tag->fields, visitor, userdata); + ast_visit(def->namespace, visitor, userdata); + return; + } + case LangDef: { + ast_visit(Match(ast, LangDef)->namespace, visitor, userdata); + return; + } + case Index: { + DeclareMatch(index, ast, Index); + ast_visit(index->indexed, visitor, userdata); + ast_visit(index->index, visitor, userdata); + return; + } + case FieldAccess: { + ast_visit(Match(ast, FieldAccess)->fielded, visitor, userdata); + return; + } + case Optional: { + ast_visit(Match(ast, Optional)->value, visitor, userdata); + return; + } + case NonOptional: { + ast_visit(Match(ast, NonOptional)->value, visitor, userdata); + return; + } + case DocTest: { + DeclareMatch(test, ast, DocTest); + ast_visit(test->expr, visitor, userdata); + ast_visit(test->expected, visitor, userdata); + return; + } + case Assert: { + DeclareMatch(assert, ast, Assert); + ast_visit(assert->expr, visitor, userdata); + ast_visit(assert->message, visitor, userdata); + return; + } + case Use: { + ast_visit(Match(ast, Use)->var, visitor, userdata); + return; + } + case InlineCCode: { + ast_visit_list(Match(ast, InlineCCode)->chunks, visitor, userdata); + return; + } + case Deserialize: { + ast_visit(Match(ast, Deserialize)->value, visitor, userdata); + return; + } + case Extend: { + ast_visit(Match(ast, Extend)->body, visitor, userdata); + return; + } + default: errx(1, "Visiting is not supported for this AST: %s", Text$as_c_string(ast_to_sexp(ast))); +#undef T + } +} + +static void _type_ast_visit(ast_t *ast, void *userdata) { + void (*visit)(type_ast_t *, void *) = ((Closure_t *)userdata)->fn; + userdata = ((Closure_t *)userdata)->userdata; + + switch (ast->tag) { + case Declare: { + visit(Match(ast, Declare)->type, userdata); + break; + } + case FunctionDef: { + for (arg_ast_t *arg = Match(ast, FunctionDef)->args; arg; arg = arg->next) + visit(arg->type, userdata); + visit(Match(ast, FunctionDef)->ret_type, userdata); + break; + } + case Lambda: { + for (arg_ast_t *arg = Match(ast, Lambda)->args; arg; arg = arg->next) + visit(arg->type, userdata); + visit(Match(ast, Lambda)->ret_type, userdata); + break; + } + case ConvertDef: { + for (arg_ast_t *arg = Match(ast, ConvertDef)->args; arg; arg = arg->next) + visit(arg->type, userdata); + visit(Match(ast, ConvertDef)->ret_type, userdata); + break; + } + case StructDef: { + for (arg_ast_t *field = Match(ast, StructDef)->fields; field; field = field->next) + visit(field->type, userdata); + break; + } + case EnumDef: { + for (tag_ast_t *tag = Match(ast, EnumDef)->tags; tag; tag = tag->next) { + for (arg_ast_t *field = tag->fields; field; field = field->next) { + visit(field->type, userdata); + } + } + break; + } + case InlineCCode: { + visit(Match(ast, InlineCCode)->type_ast, userdata); + break; + } + case Deserialize: { + visit(Match(ast, Deserialize)->type, userdata); + break; + } + case Extern: { + visit(Match(ast, Extern)->type, userdata); + break; + } + default: break; + } +} + +void type_ast_visit(ast_t *ast, void (*visitor)(type_ast_t *, void *), void *userdata) { + Closure_t fn = {.fn = visitor, .userdata = userdata}; + ast_visit(ast, _type_ast_visit, &fn); +} @@ -91,6 +91,7 @@ typedef enum { } type_ast_e; typedef struct tag_ast_s { + file_t *file; const char *start, *end; const char *name; arg_ast_t *fields; @@ -503,3 +504,5 @@ void visit_topologically(ast_list_t *ast, Closure_t fn); CONSTFUNC bool is_update_assignment(ast_t *ast); CONSTFUNC ast_e binop_tag(ast_e tag); CONSTFUNC bool is_binary_operation(ast_t *ast); +void ast_visit(ast_t *ast, void (*visitor)(ast_t *, void *), void *userdata); +void type_ast_visit(ast_t *ast, void (*visitor)(type_ast_t *, void *), void *userdata); diff --git a/src/compile/enums.c b/src/compile/enums.c index f5500831..f8a3994e 100644 --- a/src/compile/enums.c +++ b/src/compile/enums.c @@ -8,15 +8,13 @@ #include "../typecheck.h" #include "compilation.h" -Text_t compile_enum_typeinfo(env_t *env, ast_t *ast) { - DeclareMatch(def, ast, EnumDef); - +Text_t compile_enum_typeinfo(env_t *env, const char *name, tag_ast_t *tags) { // Compile member types and constructors: Text_t member_typeinfos = EMPTY_TEXT; - for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { + for (tag_ast_t *tag = tags; tag; tag = tag->next) { if (!tag->fields) continue; - const char *tag_name = String(def->name, "$", tag->name); + const char *tag_name = String(name, "$", tag->name); type_t *tag_type = Table$str_get(*env->types, tag_name); assert(tag_type && tag_type->tag == StructType); member_typeinfos = @@ -24,21 +22,21 @@ Text_t compile_enum_typeinfo(env_t *env, ast_t *ast) { } int num_tags = 0; - for (tag_ast_t *t = def->tags; t; t = t->next) + for (tag_ast_t *t = tags; t; t = t->next) num_tags += 1; - type_t *t = Table$str_get(*env->types, def->name); + type_t *t = Table$str_get(*env->types, name); const char *metamethods = is_packed_data(t) ? "PackedDataEnum$metamethods" : "Enum$metamethods"; - Text_t info = namespace_name(env, env->namespace, Texts(def->name, "$$info")); + Text_t info = namespace_name(env, env->namespace, Texts(name, "$$info")); Text_t typeinfo = Texts("public const TypeInfo_t ", info, " = {", (int64_t)type_size(t), "u, ", (int64_t)type_align(t), - "u, .metamethods=", metamethods, ", {.tag=EnumInfo, .EnumInfo={.name=\"", def->name, + "u, .metamethods=", metamethods, ", {.tag=EnumInfo, .EnumInfo={.name=\"", name, "\", " ".num_tags=", (int64_t)num_tags, ", .tags=(NamedType_t[]){"); - for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { - const char *tag_type_name = String(def->name, "$", tag->name); + for (tag_ast_t *tag = tags; tag; tag = tag->next) { + const char *tag_type_name = String(name, "$", tag->name); type_t *tag_type = Table$str_get(*env->types, tag_type_name); if (tag_type && Match(tag_type, StructType)->fields) typeinfo = Texts(typeinfo, "{\"", tag->name, "\", ", compile_type_info(tag_type), "}, "); @@ -48,10 +46,9 @@ Text_t compile_enum_typeinfo(env_t *env, ast_t *ast) { return Texts(member_typeinfos, typeinfo); } -Text_t compile_enum_constructors(env_t *env, ast_t *ast) { - DeclareMatch(def, ast, EnumDef); +Text_t compile_enum_constructors(env_t *env, const char *name, tag_ast_t *tags) { Text_t constructors = EMPTY_TEXT; - for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { + for (tag_ast_t *tag = tags; tag; tag = tag->next) { if (!tag->fields) continue; Text_t arg_sig = EMPTY_TEXT; @@ -61,9 +58,9 @@ Text_t compile_enum_constructors(env_t *env, ast_t *ast) { if (field->next) arg_sig = Texts(arg_sig, ", "); } if (arg_sig.length == 0) arg_sig = Text("void"); - Text_t type_name = namespace_name(env, env->namespace, Texts(def->name, "$$type")); - Text_t tagged_name = namespace_name(env, env->namespace, Texts(def->name, "$tagged$", tag->name)); - Text_t tag_name = namespace_name(env, env->namespace, Texts(def->name, "$tag$", tag->name)); + Text_t type_name = namespace_name(env, env->namespace, Texts(name, "$$type")); + Text_t tagged_name = namespace_name(env, env->namespace, Texts(name, "$tagged$", tag->name)); + Text_t tag_name = namespace_name(env, env->namespace, Texts(name, "$tag$", tag->name)); Text_t constructor_impl = Texts("public inline ", type_name, " ", tagged_name, "(", arg_sig, ") { return (", type_name, "){.$tag=", tag_name, ", .", valid_c_name(tag->name), "={"); for (arg_ast_t *field = tag->fields; field; field = field->next) { @@ -76,16 +73,15 @@ Text_t compile_enum_constructors(env_t *env, ast_t *ast) { return constructors; } -Text_t compile_enum_header(env_t *env, ast_t *ast) { - DeclareMatch(def, ast, EnumDef); +Text_t compile_enum_header(env_t *env, const char *name, tag_ast_t *tags) { Text_t all_defs = EMPTY_TEXT; - Text_t none_name = namespace_name(env, env->namespace, Texts(def->name, "$none")); - Text_t enum_name = namespace_name(env, env->namespace, Texts(def->name, "$$enum")); + Text_t none_name = namespace_name(env, env->namespace, Texts(name, "$none")); + Text_t enum_name = namespace_name(env, env->namespace, Texts(name, "$$enum")); Text_t enum_tags = Texts("{ ", none_name, "=0, "); bool has_any_tags_with_fields = false; - for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { - Text_t tag_name = namespace_name(env, env->namespace, Texts(def->name, "$tag$", tag->name)); + for (tag_ast_t *tag = tags; tag; tag = tag->next) { + Text_t tag_name = namespace_name(env, env->namespace, Texts(name, "$tag$", tag->name)); enum_tags = Texts(enum_tags, tag_name); if (tag->next) enum_tags = Texts(enum_tags, ", "); has_any_tags_with_fields = has_any_tags_with_fields || (tag->fields != NULL); @@ -94,32 +90,32 @@ Text_t compile_enum_header(env_t *env, ast_t *ast) { if (!has_any_tags_with_fields) { Text_t enum_def = Texts("enum ", enum_name, " ", enum_tags, ";\n"); - Text_t info = namespace_name(env, env->namespace, Texts(def->name, "$$info")); + Text_t info = namespace_name(env, env->namespace, Texts(name, "$$info")); return Texts(enum_def, "extern const TypeInfo_t ", info, ";\n"); } - Text_t struct_name = namespace_name(env, env->namespace, Texts(def->name, "$$struct")); + Text_t struct_name = namespace_name(env, env->namespace, Texts(name, "$$struct")); Text_t enum_def = Texts("struct ", struct_name, " {\n" "enum ", enum_tags, " $tag;\n" "union {\n"); - for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { + for (tag_ast_t *tag = tags; tag; tag = tag->next) { if (!tag->fields) continue; - Text_t field_def = compile_struct_header( - env, - WrapAST(ast, StructDef, .name = Text$as_c_string(Texts(def->name, "$", tag->name)), .fields = tag->fields)); + Text_t field_def = compile_struct_header(env, NewAST(tag->file, tag->start, tag->end, StructDef, + .name = Text$as_c_string(Texts(name, "$", tag->name)), + .fields = tag->fields)); all_defs = Texts(all_defs, field_def); - Text_t tag_type = namespace_name(env, env->namespace, Texts(def->name, "$", tag->name, "$$type")); + Text_t tag_type = namespace_name(env, env->namespace, Texts(name, "$", tag->name, "$$type")); enum_def = Texts(enum_def, tag_type, " ", valid_c_name(tag->name), ";\n"); } enum_def = Texts(enum_def, "};\n};\n"); all_defs = Texts(all_defs, enum_def); - Text_t info = namespace_name(env, env->namespace, Texts(def->name, "$$info")); + Text_t info = namespace_name(env, env->namespace, Texts(name, "$$info")); all_defs = Texts(all_defs, "extern const TypeInfo_t ", info, ";\n"); - for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { + for (tag_ast_t *tag = tags; tag; tag = tag->next) { if (!tag->fields) continue; Text_t arg_sig = EMPTY_TEXT; @@ -129,8 +125,8 @@ Text_t compile_enum_header(env_t *env, ast_t *ast) { if (field->next) arg_sig = Texts(arg_sig, ", "); } if (arg_sig.length == 0) arg_sig = Text("void"); - Text_t enum_type = namespace_name(env, env->namespace, Texts(def->name, "$$type")); - Text_t tagged_name = namespace_name(env, env->namespace, Texts(def->name, "$tagged$", tag->name)); + Text_t enum_type = namespace_name(env, env->namespace, Texts(name, "$$type")); + Text_t tagged_name = namespace_name(env, env->namespace, Texts(name, "$tagged$", tag->name)); Text_t constructor_def = Texts(enum_type, " ", tagged_name, "(", arg_sig, ");\n"); all_defs = Texts(all_defs, constructor_def); } diff --git a/src/compile/enums.h b/src/compile/enums.h index 888fc294..9fadb345 100644 --- a/src/compile/enums.h +++ b/src/compile/enums.h @@ -8,7 +8,7 @@ #include "../types.h" Text_t compile_empty_enum(type_t *t); -Text_t compile_enum_constructors(env_t *env, ast_t *ast); +Text_t compile_enum_constructors(env_t *env, const char *name, tag_ast_t *tags); Text_t compile_enum_field_access(env_t *env, ast_t *ast); -Text_t compile_enum_header(env_t *env, ast_t *ast); -Text_t compile_enum_typeinfo(env_t *env, ast_t *ast); +Text_t compile_enum_header(env_t *env, const char *name, tag_ast_t *tags); +Text_t compile_enum_typeinfo(env_t *env, const char *name, tag_ast_t *tags); diff --git a/src/compile/files.c b/src/compile/files.c index 4d6fb1a8..7ff252c2 100644 --- a/src/compile/files.c +++ b/src/compile/files.c @@ -125,8 +125,8 @@ Text_t compile_top_level_code(env_t *env, ast_t *ast) { } case EnumDef: { DeclareMatch(def, ast, EnumDef); - Text_t code = compile_enum_typeinfo(env, ast); - code = Texts(code, compile_enum_constructors(env, ast)); + Text_t code = compile_enum_typeinfo(env, def->name, def->tags); + code = Texts(code, compile_enum_constructors(env, def->name, def->tags)); return Texts(code, compile_namespace(env, def->name, def->namespace)); } case LangDef: { @@ -162,9 +162,30 @@ Text_t compile_top_level_code(env_t *env, ast_t *ast) { } } +typedef struct { + env_t *env; + Text_t *code; +} compile_info_t; + +static void add_type_infos(type_ast_t *type_ast, void *userdata) { + if (type_ast && type_ast->tag == EnumTypeAST) { + compile_info_t *info = (compile_info_t *)userdata; + *info->code = Texts( + *info->code, + compile_enum_typeinfo(info->env, String("enum$", (int64_t)(type_ast->start - type_ast->file->text)), + Match(type_ast, EnumTypeAST)->tags), + compile_enum_constructors(info->env, String("enum$", (int64_t)(type_ast->start - type_ast->file->text)), + Match(type_ast, EnumTypeAST)->tags)); + } +} + public Text_t compile_file(env_t *env, ast_t *ast) { Text_t top_level_code = compile_top_level_code(env, ast); + + compile_info_t info = {.env = env, .code = &top_level_code}; + type_ast_visit(ast, add_type_infos, &info); + Text_t includes = EMPTY_TEXT; Text_t use_imports = EMPTY_TEXT; diff --git a/src/compile/headers.c b/src/compile/headers.c index 33a979cf..77040445 100644 --- a/src/compile/headers.c +++ b/src/compile/headers.c @@ -146,6 +146,41 @@ static void _define_types_and_funcs(compile_typedef_info_t *info, ast_t *ast) { compile_statement_namespace_header(info->env, info->header_path, ast)); } +static void add_type_headers(type_ast_t *type_ast, void *userdata) { + if (!type_ast) return; + + if (type_ast->tag == EnumTypeAST) { + compile_typedef_info_t *info = (compile_typedef_info_t *)userdata; + DeclareMatch(enum_, type_ast, EnumTypeAST); + bool has_any_tags_with_fields = false; + for (tag_ast_t *tag = enum_->tags; tag; tag = tag->next) { + has_any_tags_with_fields = has_any_tags_with_fields || (tag->fields != NULL); + } + + const char *name = String("enum$", (int64_t)(type_ast->start - type_ast->file->text)); + if (has_any_tags_with_fields) { + Text_t struct_name = namespace_name(info->env, info->env->namespace, Texts(name, "$$struct")); + Text_t type_name = namespace_name(info->env, info->env->namespace, Texts(name, "$$type")); + *info->header = Texts(*info->header, "typedef struct ", struct_name, " ", type_name, ";\n"); + + for (tag_ast_t *tag = enum_->tags; tag; tag = tag->next) { + if (!tag->fields) continue; + Text_t tag_struct = + namespace_name(info->env, info->env->namespace, Texts(name, "$", tag->name, "$$struct")); + Text_t tag_type = + namespace_name(info->env, info->env->namespace, Texts(name, "$", tag->name, "$$type")); + *info->header = Texts(*info->header, "typedef struct ", tag_struct, " ", tag_type, ";\n"); + } + } else { + Text_t enum_name = namespace_name(info->env, info->env->namespace, Texts(name, "$$enum")); + Text_t type_name = namespace_name(info->env, info->env->namespace, Texts(name, "$$type")); + *info->header = Texts(*info->header, "typedef enum ", enum_name, " ", type_name, ";\n"); + } + + *info->header = Texts(*info->header, compile_enum_header(info->env, name, enum_->tags)); + } +} + public Text_t compile_file_header(env_t *env, Path_t header_path, ast_t *ast) { Text_t header = @@ -155,6 +190,9 @@ Text_t compile_file_header(env_t *env, Path_t header_path, ast_t *ast) { compile_typedef_info_t info = {.env = env, .header = &header, .header_path = header_path}; visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn = (void *)_make_typedefs, &info}); + + type_ast_visit(ast, add_type_headers, &info); + visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn = (void *)_define_types_and_funcs, &info}); header = Texts(header, "void ", namespace_name(env, env->namespace, Text("$initialize")), "(void);\n"); @@ -211,7 +249,8 @@ Text_t compile_statement_type_header(env_t *env, Path_t header_path, ast_t *ast) return compile_struct_header(env, ast); } case EnumDef: { - return compile_enum_header(env, ast); + DeclareMatch(def, ast, EnumDef); + return compile_enum_header(env, def->name, def->tags); } case LangDef: { DeclareMatch(def, ast, LangDef); diff --git a/src/parse/typedefs.c b/src/parse/typedefs.c index 6e5e40d0..50562536 100644 --- a/src/parse/typedefs.c +++ b/src/parse/typedefs.c @@ -134,8 +134,8 @@ ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) { fields = NULL; } - tags = new (tag_ast_t, .start = tag_start, .end = pos, .name = tag_name, .fields = fields, .secret = secret, - .next = tags); + tags = new (tag_ast_t, .file = ctx->file, .start = tag_start, .end = pos, .name = tag_name, .fields = fields, + .secret = secret, .next = tags); if (!match_separator(ctx, &pos)) break; } diff --git a/src/parse/types.c b/src/parse/types.c index 683e51ce..d87fc628 100644 --- a/src/parse/types.c +++ b/src/parse/types.c @@ -124,8 +124,8 @@ type_ast_t *parse_enum_type(parse_ctx_t *ctx, const char *pos) { fields = NULL; } - tags = new (tag_ast_t, .start = tag_start, .end = pos, .name = tag_name, .fields = fields, .secret = secret, - .next = tags); + tags = new (tag_ast_t, .file = ctx->file, .start = tag_start, .end = pos, .name = tag_name, .fields = fields, + .secret = secret, .next = tags); if (!match_separator(ctx, &pos)) break; } diff --git a/src/typecheck.c b/src/typecheck.c index 86876c30..806cf1bf 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -146,7 +146,7 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast) { .next = fields); } REVERSE_LIST(fields); - const char *struct_name = String(enum_name, "$$", tag_ast->name); + const char *struct_name = String(enum_name, "$", tag_ast->name); env_t *struct_env = namespace_env(env, struct_name); type_t *tag_type = Type(StructType, .name = tag_ast->name, .fields = fields, .env = struct_env); tags = new (tag_t, .name = tag_ast->name, .tag_value = tag_value, .type = tag_type, .next = tags); |
