/** * @file ast_dump.c * @brief AST dump 实现 */ #include #define PRINT_VALUE(ctx, fmt, value) \ SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->value_color, fmt, value) #define PRINT_NODE(ctx, name, value) \ SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s", name) #define PRINT_QUOTED_VALUE(ctx, str) \ SCC_TREE_DUMP_PRINT_AROUND(ctx, ctx->value_color, "'", "%s", str) // 获取节点类型的字符串表示 static const char *get_node_type_str(scc_ast_node_type_t type) { switch (type) { // 声明类型 case SCC_AST_DECL_VAR: return "VarDecl"; case SCC_AST_DECL_FUNC: return "FuncDecl"; case SCC_AST_DECL_PARAM: return "ParamDecl"; case SCC_AST_DECL_STRUCT: return "StructDecl"; case SCC_AST_DECL_UNION: return "UnionDecl"; case SCC_AST_DECL_ENUM: return "EnumDecl"; case SCC_AST_DECL_TYPEDEF: return "TypedefDecl"; // 语句类型 case SCC_AST_STMT_COMPOUND: return "CompoundStmt"; case SCC_AST_STMT_EXPR: return "ExprStmt"; case SCC_AST_STMT_IF: return "IfStmt"; case SCC_AST_STMT_WHILE: return "WhileStmt"; case SCC_AST_STMT_DO_WHILE: return "DoStmt"; case SCC_AST_STMT_FOR: return "ForStmt"; case SCC_AST_STMT_SWITCH: return "SwitchStmt"; case SCC_AST_STMT_CASE: return "CaseStmt"; case SCC_AST_STMT_DEFAULT: return "DefaultStmt"; case SCC_AST_STMT_BREAK: return "BreakStmt"; case SCC_AST_STMT_CONTINUE: return "ContinueStmt"; case SCC_AST_STMT_RETURN: return "ReturnStmt"; case SCC_AST_STMT_GOTO: return "GotoStmt"; case SCC_AST_STMT_LABEL: return "LabelStmt"; // 表达式类型 case SCC_AST_EXPR_BINARY: return "BinaryOperator"; case SCC_AST_EXPR_UNARY: return "UnaryOperator"; case SCC_AST_EXPR_COND: return "ConditionalOperator"; case SCC_AST_EXPR_CALL: return "CallExpr"; case SCC_AST_EXPR_ARRAY_SUBSCRIPT: return "ArraySubscriptExpr"; case SCC_AST_EXPR_MEMBER: return "MemberExpr"; case SCC_AST_EXPR_PTR_MEMBER: return "PtrMemberExpr"; case SCC_AST_EXPR_CAST: return "CastExpr"; case SCC_AST_EXPR_SIZE_OF: return "SizeOfExpr"; case SCC_AST_EXPR_ALIGN_OF: return "AlignOfExpr"; case SCC_AST_EXPR_COMPOUND_LITERAL: return "CompoundLiteralExpr"; case SCC_AST_EXPR_INT_LITERAL: return "IntegerLiteral"; case SCC_AST_EXPR_FLOAT_LITERAL: return "FloatingLiteral"; case SCC_AST_EXPR_CHAR_LITERAL: return "CharacterLiteral"; case SCC_AST_EXPR_STRING_LITERAL: return "StringLiteral"; case SCC_AST_EXPR_IDENTIFIER: return "DeclRefExpr"; // 类型类型 case SCC_AST_TYPE_BUILTIN: return "BuiltinType"; case SCC_AST_TYPE_POINTER: return "PointerType"; case SCC_AST_TYPE_ARRAY: return "ArrayType"; case SCC_AST_TYPE_FUNCTION: return "FunctionType"; case SCC_AST_TYPE_STRUCT: return "RecordType"; case SCC_AST_TYPE_UNION: return "RecordType"; case SCC_AST_TYPE_ENUM: return "EnumType"; case SCC_AST_TYPE_TYPEDEF: return "TypedefType"; // 根节点 case SCC_AST_TRANSLATION_UNIT: return "TranslationUnitDecl"; default: return "UnknownNode"; } } // 获取内置类型名称 static const char *get_builtin_type_str(scc_ast_builtin_type_t type) { switch (type) { case TYPE_VOID: return "void"; case TYPE_CHAR: return "char"; case TYPE_SHORT: return "short"; case TYPE_INT: return "int"; case TYPE_LONG: return "long"; case TYPE_LONG_LONG: return "long long"; case TYPE_FLOAT: return "float"; case TYPE_DOUBLE: return "double"; case TYPE_LONG_DOUBLE: return "long double"; case TYPE_BOOL: return "_Bool"; case TYPE_COMPLEX_FLOAT: return "float _Complex"; case TYPE_COMPLEX_DOUBLE: return "double _Complex"; case TYPE_COMPLEX_LONG_DOUBLE: return "long double _Complex"; default: return ""; } } // 获取操作符字符串 static const char *get_op_str(scc_ast_expr_op_t op) { switch (op) { case SCC_AST_OP_ASSIGN: return "="; case SCC_AST_OP_ASSIGN_ADD: return "+="; case SCC_AST_OP_ASSIGN_SUB: return "-="; case SCC_AST_OP_ASSIGN_MUL: return "*="; case SCC_AST_OP_ASSIGN_DIV: return "/="; case SCC_AST_OP_ASSIGN_MOD: return "%="; case SCC_AST_OP_ASSIGN_AND: return "&="; case SCC_AST_OP_ASSIGN_XOR: return "^="; case SCC_AST_OP_ASSIGN_OR: return "|="; case SCC_AST_OP_ASSIGN_LSHIFT: return "<<="; case SCC_AST_OP_ASSIGN_RSHIFT: return ">>="; case SCC_AST_OP_CONDITIONAL: return "? :"; case SCC_AST_OP_LOGICAL_OR: return "||"; case SCC_AST_OP_LOGICAL_AND: return "&&"; case SCC_AST_OP_BITWISE_OR: return "|"; case SCC_AST_OP_BITWISE_XOR: return "^"; case SCC_AST_OP_BITWISE_AND: return "&"; case SCC_AST_OP_EQUAL: return "=="; case SCC_AST_OP_NOT_EQUAL: return "!="; case SCC_AST_OP_LESS: return "<"; case SCC_AST_OP_GREATER: return ">"; case SCC_AST_OP_LESS_EQUAL: return "<="; case SCC_AST_OP_GREATER_EQUAL: return ">="; case SCC_AST_OP_LEFT_SHIFT: return "<<"; case SCC_AST_OP_RIGHT_SHIFT: return ">>"; case SCC_AST_OP_ADD: return "+"; case SCC_AST_OP_SUB: return "-"; case SCC_AST_OP_MUL: return "*"; case SCC_AST_OP_DIV: return "/"; case SCC_AST_OP_MOD: return "%"; case SCC_AST_OP_UNARY_PLUS: return "+"; case SCC_AST_OP_UNARY_MINUS: return "-"; case SCC_AST_OP_ADDRESS_OF: return "&"; case SCC_AST_OP_INDIRECTION: return "*"; case SCC_AST_OP_BITWISE_NOT: return "~"; case SCC_AST_OP_LOGICAL_NOT: return "!"; case SCC_AST_OP_PREFIX_INCREMENT: return "++"; case SCC_AST_OP_PREFIX_DECREMENT: return "--"; case SCC_AST_OP_POSTFIX_INCREMENT: return "++"; case SCC_AST_OP_POSTFIX_DECREMENT: return "--"; case SCC_AST_OP_MEMBER_ACCESS: return "."; case SCC_AST_OP_PTR_MEMBER_ACCESS: return "->"; default: return ""; } } // 通用的开始节点打印函数 static inline void start_node_dump(scc_ast_node_t *node, scc_tree_dump_ctx_t *ctx) { scc_tree_print_indent(ctx); SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s", get_node_type_str(node->type)); } // 通用的结束节点打印函数 static inline void end_node_dump(scc_tree_dump_ctx_t *ctx) { scc_printf("\n"); } // 通用的递归转储辅助函数 static inline void dump_child_node(scc_ast_node_t *child, scc_tree_dump_ctx_t *ctx, cbool is_last) { if (!child) return; scc_vec_push(ctx->stack, is_last); scc_ast_dump_node(ctx, child); scc_vec_pop(ctx->stack); } // 用于构建复合类型名称的宏 #define BUILD_TYPE_NAME(ctx, prefix, name) \ do { \ if (ctx->use_color) { \ scc_printf("%s'%s%s%s'%s", ctx->value_color, prefix, name, \ ctx->reset_color, ctx->reset_color); \ } else { \ scc_printf("'%s%s'", prefix, name); \ } \ } while (0) // 递归转储类型 static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) { if (!type) return; start_node_dump(&type->base, ctx); // 根据类型输出特定信息 switch (type->base.type) { case SCC_AST_TYPE_BUILTIN: PRINT_QUOTED_VALUE(ctx, get_builtin_type_str(type->builtin.builtin)); break; case SCC_AST_TYPE_POINTER: if (type->pointer.pointee && type->pointer.pointee->base.type == SCC_AST_TYPE_BUILTIN) { const char *base_type = get_builtin_type_str(type->pointer.pointee->builtin.builtin); if (ctx->use_color) { scc_printf("%s'%s *'%s", ctx->value_color, base_type, ctx->reset_color); } else { scc_printf("'%s *'", base_type); } } else { PRINT_QUOTED_VALUE(ctx, "pointer"); } break; case SCC_AST_TYPE_ARRAY: PRINT_QUOTED_VALUE(ctx, "array"); break; case SCC_AST_TYPE_FUNCTION: PRINT_QUOTED_VALUE(ctx, "function"); scc_printf("\n"); if (type->function.return_type) { dump_type_impl(type->function.return_type, ctx); } if (scc_vec_size(type->function.param_types) != 0) { scc_vec_foreach(type->function.param_types, i) { dump_type_impl(scc_vec_at(type->function.param_types, i), ctx); } } else { start_node_dump(&type->base, ctx); PRINT_QUOTED_VALUE(ctx, "void"); // TODO? } break; case SCC_AST_TYPE_STRUCT: if (type->record.name) { BUILD_TYPE_NAME(ctx, "struct ", type->record.name); } else { PRINT_QUOTED_VALUE(ctx, "anonymous struct"); } break; case SCC_AST_TYPE_UNION: if (type->record.name) { BUILD_TYPE_NAME(ctx, "union ", type->record.name); } else { PRINT_QUOTED_VALUE(ctx, "anonymous union"); } break; case SCC_AST_TYPE_ENUM: if (type->enumeration.name) { BUILD_TYPE_NAME(ctx, "enum ", type->enumeration.name); } else { PRINT_QUOTED_VALUE(ctx, "anonymous enum"); } break; case SCC_AST_TYPE_TYPEDEF: PRINT_QUOTED_VALUE(ctx, type->typedef_type.name); break; default: break; } end_node_dump(ctx); // 递归转储子节点 switch (type->base.type) { case SCC_AST_TYPE_POINTER: dump_child_node((scc_ast_node_t *)type->pointer.pointee, ctx, true); break; case SCC_AST_TYPE_ARRAY: dump_child_node((scc_ast_node_t *)type->array.element, ctx, type->array.size == NULL); if (type->array.size) { dump_child_node((scc_ast_node_t *)type->array.size, ctx, true); } break; default: break; } } // 递归转储表达式 static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) { if (!expr) return; start_node_dump(&expr->base, ctx); // 根据表达式类型输出特定信息 switch (expr->base.type) { case SCC_AST_EXPR_BINARY: PRINT_QUOTED_VALUE(ctx, get_op_str(expr->binary.op)); break; case SCC_AST_EXPR_UNARY: PRINT_QUOTED_VALUE(ctx, get_op_str(expr->unary.op)); break; case SCC_AST_EXPR_INT_LITERAL: case SCC_AST_EXPR_FLOAT_LITERAL: case SCC_AST_EXPR_CHAR_LITERAL: case SCC_AST_EXPR_STRING_LITERAL: PRINT_VALUE(ctx, " %s", expr->literal.lexme); break; case SCC_AST_EXPR_IDENTIFIER: if (expr->identifier.name) { PRINT_QUOTED_VALUE(ctx, expr->identifier.name); } break; case SCC_AST_EXPR_SIZE_OF: case SCC_AST_EXPR_ALIGN_OF: PRINT_QUOTED_VALUE(ctx, (expr->base.type == SCC_AST_EXPR_SIZE_OF) ? "sizeof" : "alignof"); break; default: break; } end_node_dump(ctx); // 使用辅助函数处理子节点转储 switch (expr->base.type) { case SCC_AST_EXPR_BINARY: dump_child_node((scc_ast_node_t *)expr->binary.lhs, ctx, false); dump_child_node((scc_ast_node_t *)expr->binary.rhs, ctx, true); break; case SCC_AST_EXPR_UNARY: dump_child_node((scc_ast_node_t *)expr->unary.operand, ctx, true); break; case SCC_AST_EXPR_COND: dump_child_node((scc_ast_node_t *)expr->cond.cond, ctx, false); dump_child_node((scc_ast_node_t *)expr->cond.then_expr, ctx, false); dump_child_node((scc_ast_node_t *)expr->cond.else_expr, ctx, true); break; case SCC_AST_EXPR_CALL: dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false); // 转储参数 for (size_t i = 0; i < expr->call.args.size; i++) { dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx, i == expr->call.args.size - 1); } break; case SCC_AST_EXPR_ARRAY_SUBSCRIPT: dump_child_node((scc_ast_node_t *)expr->subscript.array, ctx, false); dump_child_node((scc_ast_node_t *)expr->subscript.index, ctx, true); break; case SCC_AST_EXPR_MEMBER: case SCC_AST_EXPR_PTR_MEMBER: dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false); // 打印成员访问信息 scc_tree_print_indent(ctx); PRINT_NODE(ctx, "Member [\"%s\"]", expr->member.member_name); scc_printf("\n"); break; case SCC_AST_EXPR_CAST: dump_child_node((scc_ast_node_t *)expr->cast.type, ctx, false); dump_child_node((scc_ast_node_t *)expr->cast.expr, ctx, true); break; case SCC_AST_EXPR_SIZE_OF: case SCC_AST_EXPR_ALIGN_OF: if (expr->attr_of.expr) { dump_child_node((scc_ast_node_t *)expr->attr_of.expr, ctx, true); } else if (expr->attr_of.type) { dump_child_node((scc_ast_node_t *)expr->attr_of.type, ctx, true); } break; case SCC_AST_EXPR_COMPOUND_LITERAL: dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx, false); // 初始化列表 for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) { dump_child_node( (scc_ast_node_t *)expr->compound_literal.init_list.data[i], ctx, i == expr->compound_literal.init_list.size - 1); } break; default: break; } } // 递归转储语句 static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) { if (!stmt) return; start_node_dump(&stmt->base, ctx); // 根据语句类型输出特定信息 switch (stmt->base.type) { case SCC_AST_STMT_IF: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->if_stmt.cond, ctx, false); dump_child_node((scc_ast_node_t *)stmt->if_stmt.then_stmt, ctx, !stmt->if_stmt.opt_else_stmt); if (stmt->if_stmt.opt_else_stmt) { dump_child_node((scc_ast_node_t *)stmt->if_stmt.opt_else_stmt, ctx, true); } return; case SCC_AST_STMT_WHILE: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->while_stmt.cond, ctx, false); dump_child_node((scc_ast_node_t *)stmt->while_stmt.body, ctx, true); return; case SCC_AST_STMT_DO_WHILE: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.body, ctx, false); dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.cond, ctx, true); return; case SCC_AST_STMT_SWITCH: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->switch_stmt.cond, ctx, false); dump_child_node((scc_ast_node_t *)stmt->switch_stmt.body, ctx, true); return; case SCC_AST_STMT_FOR: end_node_dump(ctx); if (stmt->for_stmt.init) { dump_child_node((scc_ast_node_t *)stmt->for_stmt.init, ctx, false); } if (stmt->for_stmt.cond) { dump_child_node((scc_ast_node_t *)stmt->for_stmt.cond, ctx, false); } if (stmt->for_stmt.iter) { dump_child_node((scc_ast_node_t *)stmt->for_stmt.iter, ctx, false); } dump_child_node((scc_ast_node_t *)stmt->for_stmt.body, ctx, true); return; case SCC_AST_STMT_RETURN: if (stmt->return_stmt.expr) { end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->return_stmt.expr, ctx, true); } else { end_node_dump(ctx); } break; case SCC_AST_STMT_GOTO: if (stmt->goto_stmt.label) { PRINT_VALUE(ctx, " Label: %s", stmt->goto_stmt.label); } end_node_dump(ctx); break; case SCC_AST_STMT_LABEL: if (stmt->label_stmt.label) { PRINT_VALUE(ctx, " %s", stmt->label_stmt.label); } end_node_dump(ctx); break; case SCC_AST_STMT_COMPOUND: end_node_dump(ctx); for (size_t i = 0; i < stmt->compound.block_items.size; i++) { scc_ast_node_t *item = (scc_ast_node_t *)stmt->compound.block_items.data[i]; dump_child_node(item, ctx, i == stmt->compound.block_items.size - 1); } break; case SCC_AST_STMT_EXPR: end_node_dump(ctx); if (stmt->expr.expr) { dump_child_node((scc_ast_node_t *)stmt->expr.expr, ctx, true); } break; case SCC_AST_STMT_CASE: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->case_stmt.expr, ctx, false); dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true); break; case SCC_AST_STMT_DEFAULT: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true); break; default: LOG_WARN("unknown node type %d", stmt->base.type); break; } } // 递归转储声明 static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) { if (!decl) return; start_node_dump(&decl->base, ctx); // 根据声明类型输出特定信息 switch (decl->base.type) { case SCC_AST_DECL_VAR: if (decl->var.name) { PRINT_QUOTED_VALUE(ctx, decl->var.name); } break; case SCC_AST_DECL_FUNC: if (decl->func.name) { PRINT_QUOTED_VALUE(ctx, decl->func.name); } break; case SCC_AST_DECL_PARAM: if (decl->param.name) { PRINT_QUOTED_VALUE(ctx, decl->param.name); } break; case SCC_AST_DECL_STRUCT: if (decl->record.name) { PRINT_QUOTED_VALUE(ctx, decl->record.name); } break; case SCC_AST_DECL_UNION: if (decl->record.name) { PRINT_QUOTED_VALUE(ctx, decl->record.name); } break; case SCC_AST_DECL_ENUM: if (decl->enumeration.name) { PRINT_QUOTED_VALUE(ctx, decl->enumeration.name); } break; case SCC_AST_DECL_TYPEDEF: if (decl->typedef_decl.name) { PRINT_QUOTED_VALUE(ctx, decl->typedef_decl.name); } break; default: break; } end_node_dump(ctx); // 递归转储子节点 switch (decl->base.type) { case SCC_AST_DECL_VAR: if (decl->var.type) { dump_child_node((scc_ast_node_t *)decl->var.type, ctx, decl->var.init == NULL); if (decl->var.init) { dump_child_node((scc_ast_node_t *)decl->var.init, ctx, true); } } break; case SCC_AST_DECL_FUNC: if (decl->func.type) { dump_child_node((scc_ast_node_t *)decl->func.type, ctx, decl->func.body == NULL); if (decl->func.body) { dump_child_node((scc_ast_node_t *)decl->func.body, ctx, true); } } break; case SCC_AST_DECL_PARAM: if (decl->param.type) { dump_child_node((scc_ast_node_t *)decl->param.type, ctx, true); } break; case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: for (size_t i = 0; i < decl->record.fields.size; i++) { dump_child_node((scc_ast_node_t *)decl->record.fields.data[i], ctx, i == decl->record.fields.size - 1); } break; case SCC_AST_DECL_ENUM: for (size_t i = 0; i < decl->enumeration.enumerators.size; i++) { dump_child_node( (scc_ast_node_t *)decl->enumeration.enumerators.data[i], ctx, i == decl->enumeration.enumerators.size - 1); } break; case SCC_AST_DECL_TYPEDEF: if (decl->typedef_decl.type) { dump_child_node((scc_ast_node_t *)decl->typedef_decl.type, ctx, true); } break; default: break; } } // 递归转储翻译单元 static void dump_unit_impl(scc_ast_translation_unit_t *unit, scc_tree_dump_ctx_t *ctx) { if (!unit) return; start_node_dump(&unit->base, ctx); end_node_dump(ctx); for (size_t i = 0; i < unit->declarations.size; i++) { dump_child_node((scc_ast_node_t *)unit->declarations.data[i], ctx, i == unit->declarations.size - 1); } } void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node) { if (!node) return; if (SCC_AST_IS_A(scc_ast_expr_t, node)) { dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), ctx); } else if (SCC_AST_IS_A(scc_ast_stmt_t, node)) { dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), ctx); } else if (SCC_AST_IS_A(scc_ast_decl_t, node)) { dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), ctx); } else if (SCC_AST_IS_A(scc_ast_type_t, node)) { dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), ctx); } else if (SCC_AST_IS_A(scc_ast_translation_unit_t, node)) { dump_unit_impl(SCC_AST_CAST_TO(scc_ast_translation_unit_t, node), ctx); } }