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:
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user