feat(ast): 更新AST dump功能以使用新的树转储接口

- 将头文件中的tree_dump.h替换为scc_tree_dump.h
- 修改函数签名将scc_tree_dump_ctx_t改为scc_tree_dump_t
- 移除过时的宏定义和内联函数实现
- 使用新的scc_tree_dump_* API替代旧的PRINT_*宏
- 简化类型、表达式、语句和声明的转储逻辑
- 统一使用新的树转储接口进行节点和值的输出

feat(ast2ir): 实现逻辑运算符和一元运算符的IR转换

- 添加scc_ast2ir_logical_expr函数处理&&和||运算符
- 实现短路求值逻辑,包含分支控制流
- 添加对一元正号运算符的支持
- 实现取地址和间接寻址运算符
- 添加字符字面量解析支持转义序列

fix(ir): 修复字符串常量构建中的长度计算错误

- 修正数组长度计算从len+1改为len-1
- 调整字符串内容复制逻辑跳过引号边界
- 修正内存分配大小与实际数据长度匹配

refactor(ir): 更新IR转储模块使用统一的树转储接口

- 将IR转储上下文中的tree_dump_ctx_t替换为scc_tree_dump_t
- 更新初始化函数签名以使用新的转储接口类型
This commit is contained in:
zzy
2026-04-03 20:10:51 +08:00
parent 78e7c800ba
commit ca187c78f1
42 changed files with 1264 additions and 1212 deletions

View File

@@ -7,7 +7,7 @@
#define __SCC_AST_DUMP_H__
#include "ast_def.h"
#include <tree_dump.h>
#include <scc_tree_dump.h>
/**
* @brief 以指定格式 dump AST
@@ -15,6 +15,6 @@
* @param node AST 节点(可以是任意类型的节点)
* @param ctx dump 上下文
*/
void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node);
void scc_ast_dump_node(scc_tree_dump_t *ctx, const scc_ast_node_t *node);
#endif /* __SCC_AST_DUMP_H__ */

View File

@@ -4,15 +4,7 @@
*/
#include <ast_dump.h>
#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)
#include <scc_tree_dump.h>
static const char *node_type_names[] = {
[SCC_AST_UNKNOWN] = "Unknown",
@@ -112,7 +104,6 @@ static const char *get_builtin_type_str(scc_ast_builtin_type_t type) {
return builtin_type_names[type];
}
// 获取操作符字符串
static const char *get_op_str(scc_ast_expr_op_t op) {
switch (op) {
case SCC_AST_OP_ASSIGN:
@@ -200,484 +191,374 @@ static const char *get_op_str(scc_ast_expr_op_t op) {
}
}
// 通用的开始节点打印函数
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_tree_dump_printf(ctx, "\n");
}
// 通用的递归转储辅助函数
static inline void dump_child_node(scc_ast_node_t *child,
scc_tree_dump_ctx_t *ctx, cbool is_last) {
static inline void dump_child_node(scc_tree_dump_t *td, scc_ast_node_t *child,
cbool is_last) {
if (!child)
return;
scc_vec_push(ctx->stack, is_last);
scc_ast_dump_node(ctx, child);
(void)scc_vec_pop(ctx->stack);
scc_tree_dump_push(td, is_last);
scc_ast_dump_node(td, child);
scc_tree_dump_pop(td);
}
// 用于构建复合类型名称的宏
#define BUILD_TYPE_NAME(ctx, prefix, name) \
do { \
if (ctx->use_color) { \
scc_tree_dump_printf(ctx, "%s'%s%s%s'%s", ctx->value_color, \
prefix, name, ctx->reset_color, \
ctx->reset_color); \
} else { \
scc_tree_dump_printf(ctx, "'%s%s'", prefix, name); \
} \
} while (0)
static inline void dump_quals(scc_ast_decl_specifier_t quals,
scc_tree_dump_ctx_t *ctx) {
if (quals.is_atomic) {
PRINT_QUOTED_VALUE(ctx, "atomic");
}
if (quals.is_restrict) {
PRINT_QUOTED_VALUE(ctx, "restrict");
}
if (quals.is_volatile) {
PRINT_QUOTED_VALUE(ctx, "volatile");
}
if (quals.is_const) {
PRINT_QUOTED_VALUE(ctx, "const");
}
if (quals.is_inline) {
PRINT_QUOTED_VALUE(ctx, "inline");
}
if (quals.is_extern) {
PRINT_QUOTED_VALUE(ctx, "extern");
}
scc_tree_dump_t *td) {
if (quals.is_atomic)
scc_tree_dump_value(td, " atomic");
if (quals.is_restrict)
scc_tree_dump_value(td, " restrict");
if (quals.is_volatile)
scc_tree_dump_value(td, " volatile");
if (quals.is_const)
scc_tree_dump_value(td, " const");
if (quals.is_inline)
scc_tree_dump_value(td, " inline");
if (quals.is_extern)
scc_tree_dump_value(td, " extern");
}
// 递归转储类型
static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) {
if (!type)
return;
start_node_dump(&type->base, ctx);
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "%s", get_node_type_str(type->base.type));
dump_quals(type->quals, td);
dump_quals(type->quals, ctx);
// 根据类型输出特定信息
switch (type->base.type) {
case SCC_AST_TYPE_BUILTIN:
PRINT_QUOTED_VALUE(ctx, get_builtin_type_str(type->builtin.type));
scc_tree_dump_value(td, " '%s'",
get_builtin_type_str(type->builtin.type));
break;
case SCC_AST_TYPE_POINTER:
PRINT_QUOTED_VALUE(ctx, "pointer");
scc_tree_dump_value(td, " pointer");
break;
case SCC_AST_TYPE_ARRAY:
PRINT_QUOTED_VALUE(ctx, "array");
scc_tree_dump_value(td, " array");
break;
case SCC_AST_TYPE_FUNCTION:
PRINT_QUOTED_VALUE(ctx, "function");
scc_tree_dump_value(td, " function");
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>");
}
if (type->record.name)
scc_tree_dump_value(td, " 'struct %s'", type->record.name);
else
scc_tree_dump_value(td, " <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>");
}
if (type->record.name)
scc_tree_dump_value(td, " 'union %s'", type->record.name);
else
scc_tree_dump_value(td, " <anonymous union>");
break;
case SCC_AST_TYPE_ENUM:
if (type->record.name) {
BUILD_TYPE_NAME(ctx, "enum ", type->record.name);
} else {
PRINT_QUOTED_VALUE(ctx, "anonymous enum");
}
if (type->record.name)
scc_tree_dump_value(td, " 'enum %s'", type->record.name);
else
scc_tree_dump_value(td, " anonymous enum");
break;
case SCC_AST_TYPE_TYPEDEF:
PRINT_QUOTED_VALUE(ctx, type->typedef_type.name);
scc_tree_dump_value(td, " '%s'", 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);
dump_child_node(td, (scc_ast_node_t *)type->pointer.pointee, true);
break;
case SCC_AST_TYPE_ARRAY:
dump_child_node((scc_ast_node_t *)type->array.element, ctx,
dump_child_node(td, (scc_ast_node_t *)type->array.element,
type->array.size == NULL);
if (type->array.size) {
dump_child_node((scc_ast_node_t *)type->array.size, ctx, true);
}
if (type->array.size)
dump_child_node(td, (scc_ast_node_t *)type->array.size, true);
break;
case SCC_AST_TYPE_FUNCTION:
scc_vec_push(ctx->stack, false);
scc_tree_print_indent(ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s\n", "ReturnType");
dump_child_node((scc_ast_node_t *)type->function.return_type, ctx,
true);
(void)scc_vec_pop(ctx->stack);
scc_tree_dump_push(td, false);
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "%s", "ReturnType");
dump_child_node(td, (scc_ast_node_t *)type->function.return_type, true);
scc_tree_dump_pop(td);
scc_vec_push(ctx->stack, true);
scc_tree_dump_push(td, true);
if (scc_vec_size(type->function.params) != 0) {
scc_vec_foreach(type->function.params, i) {
scc_ast_decl_t *param = scc_vec_at(type->function.params, i);
if (param->name) {
// FIXME param name
}
dump_type_impl(param->param.type, ctx);
dump_type_impl(param->param.type, td);
}
} else {
scc_tree_print_indent(ctx);
PRINT_QUOTED_VALUE(ctx, "()");
scc_tree_dump_printf(ctx, "\n");
scc_tree_dump_begin_line(td);
scc_tree_dump_value(td, "()");
}
(void)scc_vec_pop(ctx->stack);
scc_tree_dump_pop(td);
break;
default:
break;
}
}
// 递归转储表达式
static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_t *td) {
if (!expr)
return;
start_node_dump(&expr->base, ctx);
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "%s", get_node_type_str(expr->base.type));
// 根据表达式类型输出特定信息
switch (expr->base.type) {
case SCC_AST_EXPR_BINARY:
PRINT_QUOTED_VALUE(ctx, get_op_str(expr->binary.op));
scc_tree_dump_value(td, " '%s'", get_op_str(expr->binary.op));
break;
case SCC_AST_EXPR_UNARY:
PRINT_QUOTED_VALUE(ctx, get_op_str(expr->unary.op));
scc_tree_dump_value(td, " '%s'", 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);
scc_tree_dump_value(td, " %s", expr->literal.lexme);
break;
case SCC_AST_EXPR_IDENTIFIER:
if (expr->identifier.name) {
PRINT_QUOTED_VALUE(ctx, expr->identifier.name);
}
if (expr->identifier.name)
scc_tree_dump_value(td, " '%s'", 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");
scc_tree_dump_value(
td, " '%s'",
(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);
dump_child_node(td, (scc_ast_node_t *)expr->binary.lhs, false);
dump_child_node(td, (scc_ast_node_t *)expr->binary.rhs, true);
break;
case SCC_AST_EXPR_UNARY:
dump_child_node((scc_ast_node_t *)expr->unary.operand, ctx, true);
dump_child_node(td, (scc_ast_node_t *)expr->unary.operand, 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);
dump_child_node(td, (scc_ast_node_t *)expr->cond.cond, false);
dump_child_node(td, (scc_ast_node_t *)expr->cond.then_expr, false);
dump_child_node(td, (scc_ast_node_t *)expr->cond.else_expr, true);
break;
case SCC_AST_EXPR_CALL:
dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false);
// 转储参数
dump_child_node(td, (scc_ast_node_t *)expr->call.callee, 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,
dump_child_node(td, (scc_ast_node_t *)expr->call.args.data[i],
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);
dump_child_node(td, (scc_ast_node_t *)expr->subscript.array, false);
dump_child_node(td, (scc_ast_node_t *)expr->subscript.index, 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_vec_push(ctx->stack, true);
scc_tree_print_indent(ctx);
SCC_TREE_DUMP_PRINT_PURE(
ctx, ctx->node_color, "%s %s\n",
expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember",
expr->member.name);
(void)scc_vec_pop(ctx->stack);
dump_child_node(td, (scc_ast_node_t *)expr->member.base, false);
scc_tree_dump_push(td, true);
scc_tree_dump_begin_line(td);
scc_tree_dump_node(
td, "%s",
expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember");
scc_tree_dump_value(td, " %s", expr->member.name);
scc_tree_dump_pop(td);
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);
dump_child_node(td, (scc_ast_node_t *)expr->cast.type, false);
dump_child_node(td, (scc_ast_node_t *)expr->cast.expr, 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);
}
if (expr->attr_of.expr)
dump_child_node(td, (scc_ast_node_t *)expr->attr_of.expr, true);
else if (expr->attr_of.type)
dump_child_node(td, (scc_ast_node_t *)expr->attr_of.type, true);
break;
case SCC_AST_EXPR_LVALUE:
dump_child_node((scc_ast_node_t *)expr->lvalue.type, ctx, true);
dump_child_node(td, (scc_ast_node_t *)expr->lvalue.type, true);
break;
case SCC_AST_EXPR_COMPOUND:;
dump_child_node((scc_ast_node_t *)expr->compound.base, ctx, false);
if (scc_vec_size(expr->compound.lhs_exprs) !=
scc_vec_size(expr->compound.rhs_exprs)) {
LOG_ERROR("compound expr lhs and rhs size not equal");
break;
}
usize size = scc_vec_size(expr->compound.lhs_exprs);
for (usize i = 0; i < size; i++) {
dump_child_node(
(scc_ast_node_t *)scc_vec_at(expr->compound.lhs_exprs, i), ctx,
false);
dump_child_node(
(scc_ast_node_t *)scc_vec_at(expr->compound.rhs_exprs, i), ctx,
i + 1 == size);
case SCC_AST_EXPR_COMPOUND:
dump_child_node(td, (scc_ast_node_t *)expr->compound.base, false);
{
usize size = scc_vec_size(expr->compound.lhs_exprs);
for (usize i = 0; i < size; i++) {
dump_child_node(
td,
(scc_ast_node_t *)scc_vec_at(expr->compound.lhs_exprs, i),
false);
dump_child_node(
td,
(scc_ast_node_t *)scc_vec_at(expr->compound.rhs_exprs, i),
i + 1 == size);
}
}
break;
case SCC_AST_EXPR_BUILTIN:
// PRINT_QUOTED_VALUE(ctx, scc_ast_builtin_type_name(expr->builtin));
break;
default:
break;
}
}
// 递归转储语句
static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_t *td) {
if (!stmt)
return;
start_node_dump(&stmt->base, ctx);
// 根据语句类型输出特定信息
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "%s", get_node_type_str(stmt->base.type));
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->while_stmt.body, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->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.incr) {
dump_child_node((scc_ast_node_t *)stmt->for_stmt.incr, 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);
if (!stmt->return_stmt.expr) {
return;
}
break;
dump_child_node(td, (scc_ast_node_t *)stmt->return_stmt.expr, true);
return;
case SCC_AST_STMT_GOTO:
if (stmt->goto_stmt.label) {
PRINT_VALUE(ctx, " Label: %s", stmt->goto_stmt.label);
}
end_node_dump(ctx);
break;
if (stmt->goto_stmt.label)
scc_tree_dump_value(td, " Label: %s", stmt->goto_stmt.label);
return;
case SCC_AST_STMT_LABEL:
if (stmt->label_stmt.label) {
PRINT_VALUE(ctx, " %s", stmt->label_stmt.label);
}
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->label_stmt.stmt, ctx, true);
break;
case SCC_AST_STMT_COMPOUND:
end_node_dump(ctx);
scc_vec_foreach(stmt->compound.block_items, i) {
dump_child_node(
(scc_ast_node_t *)scc_vec_at(stmt->compound.block_items, i),
ctx, i + 1 == stmt->compound.block_items.size);
}
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;
if (stmt->label_stmt.label)
scc_tree_dump_value(td, " %s", stmt->label_stmt.label);
dump_child_node(td, (scc_ast_node_t *)stmt->label_stmt.stmt, true);
return;
case SCC_AST_STMT_BREAK:
case SCC_AST_STMT_CONTINUE:
end_node_dump(ctx);
break;
return;
case SCC_AST_STMT_DEFAULT:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true);
break;
dump_child_node(td, (scc_ast_node_t *)stmt->default_stmt.stmt, true);
return;
case SCC_AST_STMT_COMPOUND:
scc_vec_foreach(stmt->compound.block_items, i) {
dump_child_node(
td, (scc_ast_node_t *)scc_vec_at(stmt->compound.block_items, i),
i + 1 == stmt->compound.block_items.size);
}
return;
case SCC_AST_STMT_EXPR:
if (stmt->expr.expr)
dump_child_node(td, (scc_ast_node_t *)stmt->expr.expr, true);
return;
case SCC_AST_STMT_IF:
dump_child_node(td, (scc_ast_node_t *)stmt->if_stmt.cond, false);
dump_child_node(td, (scc_ast_node_t *)stmt->if_stmt.then_stmt,
!stmt->if_stmt.opt_else_stmt);
if (stmt->if_stmt.opt_else_stmt)
dump_child_node(td, (scc_ast_node_t *)stmt->if_stmt.opt_else_stmt,
true);
return;
case SCC_AST_STMT_WHILE:
dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.cond, false);
dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.body, true);
return;
case SCC_AST_STMT_DO_WHILE:
dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.body, false);
dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.cond, true);
return;
case SCC_AST_STMT_SWITCH:
dump_child_node(td, (scc_ast_node_t *)stmt->switch_stmt.cond, false);
dump_child_node(td, (scc_ast_node_t *)stmt->switch_stmt.body, true);
return;
case SCC_AST_STMT_FOR:
if (stmt->for_stmt.init)
dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.init, false);
if (stmt->for_stmt.cond)
dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.cond, false);
if (stmt->for_stmt.incr)
dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.incr, false);
dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.body, true);
return;
case SCC_AST_STMT_CASE:
dump_child_node(td, (scc_ast_node_t *)stmt->case_stmt.expr, false);
dump_child_node(td, (scc_ast_node_t *)stmt->case_stmt.stmt, true);
return;
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) {
static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_t *td) {
if (!decl)
return;
start_node_dump(&decl->base, ctx);
if (decl->name) {
PRINT_QUOTED_VALUE(ctx, decl->name);
}
end_node_dump(ctx);
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "%s", get_node_type_str(decl->base.type));
if (decl->name)
scc_tree_dump_value(td, " '%s'", decl->name);
// 递归转储子节点
switch (decl->base.type) {
case SCC_AST_DECL_LIST:
scc_vec_foreach(decl->list.vars, i) {
dump_child_node((scc_ast_node_t *)scc_vec_at(decl->list.vars, i),
ctx, i + 1 == scc_vec_size(decl->list.vars));
dump_child_node(td,
(scc_ast_node_t *)scc_vec_at(decl->list.vars, i),
i + 1 == scc_vec_size(decl->list.vars));
}
break;
case SCC_AST_DECL_VAR:
if (decl->var.type) {
dump_child_node((scc_ast_node_t *)decl->var.type, ctx,
dump_child_node(td, (scc_ast_node_t *)decl->var.type,
decl->var.init == NULL);
if (decl->var.init) {
dump_child_node((scc_ast_node_t *)decl->var.init, ctx, true);
}
if (decl->var.init)
dump_child_node(td, (scc_ast_node_t *)decl->var.init, 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);
}
dump_child_node(td, (scc_ast_node_t *)decl->func.type,
decl->func.body == NULL);
if (decl->func.body)
dump_child_node(td, (scc_ast_node_t *)decl->func.body, true);
}
break;
case SCC_AST_DECL_PARAM:
if (decl->param.type) {
dump_child_node((scc_ast_node_t *)decl->param.type, ctx, true);
}
if (decl->param.type)
dump_child_node(td, (scc_ast_node_t *)decl->param.type, true);
break;
case SCC_AST_DECL_STRUCT:
case SCC_AST_DECL_UNION:
case SCC_AST_DECL_ENUM:
scc_vec_foreach(decl->record.fields, i) {
dump_child_node(
(scc_ast_node_t *)scc_vec_at(decl->record.fields, i), ctx,
td, (scc_ast_node_t *)scc_vec_at(decl->record.fields, i),
i + 1 == scc_vec_size(decl->record.fields));
}
break;
case SCC_AST_DECL_TYPEDEF:
if (decl->typedef_decl.type) {
dump_child_node((scc_ast_node_t *)decl->typedef_decl.type, ctx,
if (decl->typedef_decl.type)
dump_child_node(td, (scc_ast_node_t *)decl->typedef_decl.type,
true);
}
break;
default:
break;
}
}
// 递归转储翻译单元
static void dump_unit_impl(scc_ast_translation_unit_t *unit,
scc_tree_dump_ctx_t *ctx) {
scc_tree_dump_t *td) {
if (!unit)
return;
start_node_dump(&unit->base, ctx);
end_node_dump(ctx);
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "%s", get_node_type_str(unit->base.type));
scc_vec_foreach(unit->declarations, i) {
dump_child_node((scc_ast_node_t *)scc_vec_at(unit->declarations, i),
ctx, i + 1 == scc_vec_size(unit->declarations));
dump_child_node(td, (scc_ast_node_t *)scc_vec_at(unit->declarations, i),
i + 1 == scc_vec_size(unit->declarations));
}
}
void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node) {
void scc_ast_dump_node(scc_tree_dump_t *td, 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);
}
if (SCC_AST_IS_A(scc_ast_expr_t, node))
dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), td);
else if (SCC_AST_IS_A(scc_ast_stmt_t, node))
dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), td);
else if (SCC_AST_IS_A(scc_ast_decl_t, node))
dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), td);
else if (SCC_AST_IS_A(scc_ast_type_t, node))
dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), td);
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), td);
}