diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-09-21 13:38:27 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-09-21 13:38:27 -0400 |
| commit | 7204970fccd5f1903c38b97c9c0778892c44fdfe (patch) | |
| tree | db3e4afa89834c9387ac686f49ab5f777f63ed28 /src/compile/headers.c | |
| parent | e419a527a1212123946e53adaaea01df0c5605c3 (diff) | |
Got inlne enums working in most places
Diffstat (limited to 'src/compile/headers.c')
| -rw-r--r-- | src/compile/headers.c | 41 |
1 files changed, 40 insertions, 1 deletions
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); |
