diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-10-04 14:32:10 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-10-04 14:32:10 -0400 |
| commit | 70a0f59b9e97b303434047a43aa217889a5a6d61 (patch) | |
| tree | 2bc0c165449c586a0b326cb38b26609c65e6ce63 /src | |
| parent | d053a3177df6abf6e014ac00c657e3263476b7b9 (diff) | |
Fix for nested anonymous enums (visit them recursively in leaf-first
traversal)
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.c | 74 |
1 files changed, 61 insertions, 13 deletions
@@ -690,52 +690,100 @@ void ast_visit(ast_t *ast, void (*visitor)(ast_t *, void *), void *userdata) { } } -static void _type_ast_visit(ast_t *ast, void *userdata) { +static void _recursive_type_ast_visit(type_ast_t *ast, void *userdata) { + if (ast == NULL) return; + void (*visit)(type_ast_t *, void *) = ((Closure_t *)userdata)->fn; - userdata = ((Closure_t *)userdata)->userdata; + void *visitor_userdata = ((Closure_t *)userdata)->userdata; + switch (ast->tag) { + case UnknownTypeAST: + case VarTypeAST: visit(ast, visitor_userdata); break; + case PointerTypeAST: { + _recursive_type_ast_visit(Match(ast, PointerTypeAST)->pointed, userdata); + visit(ast, visitor_userdata); + break; + } + case ListTypeAST: { + _recursive_type_ast_visit(Match(ast, ListTypeAST)->item, userdata); + visit(ast, visitor_userdata); + break; + } + case TableTypeAST: { + DeclareMatch(table, ast, TableTypeAST); + _recursive_type_ast_visit(table->key, userdata); + _recursive_type_ast_visit(table->value, userdata); + visit(ast, visitor_userdata); + break; + } + case FunctionTypeAST: { + DeclareMatch(fn, ast, FunctionTypeAST); + for (arg_ast_t *arg = fn->args; arg; arg = arg->next) + _recursive_type_ast_visit(arg->type, userdata); + _recursive_type_ast_visit(fn->ret, userdata); + visit(ast, visitor_userdata); + break; + } + case OptionalTypeAST: { + _recursive_type_ast_visit(Match(ast, OptionalTypeAST)->type, userdata); + visit(ast, visitor_userdata); + break; + } + case EnumTypeAST: { + for (tag_ast_t *tag = Match(ast, EnumTypeAST)->tags; tag; tag = tag->next) { + for (arg_ast_t *field = tag->fields; field; field = field->next) { + _recursive_type_ast_visit(field->type, userdata); + } + } + visit(ast, visitor_userdata); + break; + } + default: errx(1, "Invalid type AST"); + } +} +static void _type_ast_visit(ast_t *ast, void *userdata) { switch (ast->tag) { case Declare: { - visit(Match(ast, Declare)->type, userdata); + _recursive_type_ast_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); + _recursive_type_ast_visit(arg->type, userdata); + _recursive_type_ast_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); + _recursive_type_ast_visit(arg->type, userdata); + _recursive_type_ast_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); + _recursive_type_ast_visit(arg->type, userdata); + _recursive_type_ast_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); + _recursive_type_ast_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); + _recursive_type_ast_visit(field->type, userdata); } } break; } case InlineCCode: { - visit(Match(ast, InlineCCode)->type_ast, userdata); + _recursive_type_ast_visit(Match(ast, InlineCCode)->type_ast, userdata); break; } case Deserialize: { - visit(Match(ast, Deserialize)->type, userdata); + _recursive_type_ast_visit(Match(ast, Deserialize)->type, userdata); break; } default: break; |
