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:
99
libs/tree_dump/include/scc_tree_dump.h
Normal file
99
libs/tree_dump/include/scc_tree_dump.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef SCC_TREE_DUMP_H
|
||||
#define SCC_TREE_DUMP_H
|
||||
|
||||
#include "scc_core_str.h"
|
||||
#include "scc_core_vec.h"
|
||||
|
||||
typedef struct scc_tree_dump {
|
||||
scc_str_t buf; // 字符串缓冲区
|
||||
SCC_VEC(cbool) stack; // 缩进栈:每个元素表示该层是否为最后一个子节点
|
||||
cbool use_color; // 是否启用颜色
|
||||
cbool line_start; // 当前是否在行首(需要输出缩进)
|
||||
|
||||
// 可配置的缩进字符串
|
||||
const char *vertical; // "| "
|
||||
const char *branch; // "|-"
|
||||
const char *last_branch; // "`-"
|
||||
const char *space; // " "
|
||||
|
||||
// 颜色字符串(当 use_color 为 false 时为空字符串)
|
||||
const char *node_color; // 节点名称颜色
|
||||
const char *value_color; // 值颜色
|
||||
const char *branch_color; // 分支符号颜色
|
||||
const char *reset_color; // 重置颜色
|
||||
} scc_tree_dump_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化树形输出器
|
||||
* @param td 输出器指针
|
||||
* @param use_color 是否使用 ANSI 颜色
|
||||
*/
|
||||
void scc_tree_dump_init(scc_tree_dump_t *td, cbool use_color);
|
||||
|
||||
/**
|
||||
* @brief 释放输出器占用的资源
|
||||
*/
|
||||
void scc_tree_dump_drop(scc_tree_dump_t *td);
|
||||
|
||||
/**
|
||||
* @brief 清空当前缓冲区,但保留已分配内存
|
||||
*/
|
||||
void scc_tree_dump_clear(scc_tree_dump_t *td);
|
||||
|
||||
/**
|
||||
* @brief 获取当前构建的字符串(以 '\0' 结尾)
|
||||
* @return 内部缓冲区指针,不可 free
|
||||
*/
|
||||
const char *scc_tree_dump_cstr(scc_tree_dump_t *td);
|
||||
|
||||
/**
|
||||
* @brief 将缓冲区内容通过回调输出,并清空缓冲区
|
||||
* @param output 输出回调函数,接收字符串指针、长度、用户数据
|
||||
* @param user 用户数据
|
||||
*/
|
||||
void scc_tree_dump_flush(scc_tree_dump_t *td,
|
||||
void (*output)(const char *str, usize len, void *user),
|
||||
void *user);
|
||||
|
||||
/**
|
||||
* @brief 开始一个新行(自动输出缩进)
|
||||
* @note 通常不需要手动调用,因为 append 系列函数会自动处理
|
||||
*/
|
||||
void scc_tree_dump_begin_line(scc_tree_dump_t *td);
|
||||
|
||||
/**
|
||||
* @brief 追加普通字符串(自动处理行首缩进)
|
||||
*/
|
||||
void scc_tree_dump_append(scc_tree_dump_t *td, const char *s);
|
||||
|
||||
/**
|
||||
* @brief 格式化追加(printf 风格)
|
||||
*/
|
||||
void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief 追加带节点颜色的文本
|
||||
*/
|
||||
#define scc_tree_dump_node(td, fmt, ...) \
|
||||
scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->node_color, \
|
||||
##__VA_ARGS__, (td)->reset_color)
|
||||
|
||||
/**
|
||||
* @brief 追加带值颜色的格式化文本
|
||||
*/
|
||||
#define scc_tree_dump_value(td, fmt, ...) \
|
||||
scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->value_color, \
|
||||
##__VA_ARGS__, (td)->reset_color)
|
||||
|
||||
/**
|
||||
* @brief 推入新层级
|
||||
* @param is_last 该层级是否是父节点的最后一个子节点
|
||||
*/
|
||||
void scc_tree_dump_push(scc_tree_dump_t *td, cbool is_last);
|
||||
|
||||
/**
|
||||
* @brief 弹出当前层级
|
||||
*/
|
||||
void scc_tree_dump_pop(scc_tree_dump_t *td);
|
||||
|
||||
#endif // SCC_TREE_DUMP_H
|
||||
@@ -1,119 +0,0 @@
|
||||
#ifndef __SCC_TREE_DUMP_H__
|
||||
#define __SCC_TREE_DUMP_H__
|
||||
|
||||
#include <scc_core.h>
|
||||
|
||||
#define SCC_TREE_DUMP_VERTICAL "| "
|
||||
#define SCC_TREE_DUMP_BRANCH "|-"
|
||||
#define SCC_TREE_DUMP_LAST_BRANCH "`-"
|
||||
#define SCC_TREE_DUMP_SPACE " "
|
||||
|
||||
#define SCC_TREE_DUMP_NODE_COLOR ANSI_FG_BLUE
|
||||
#define SCC_TREE_DUMP_VALUE_COLOR ANSI_FG_GREEN
|
||||
#define SCC_TREE_DUMP_BRANCH_COLOR ANSI_FG_YELLOW
|
||||
#define SCC_TREE_DUMP_RESET_COLOR ANSI_NONE
|
||||
|
||||
// #define ANSI_FMT
|
||||
|
||||
typedef SCC_VEC(cbool) scc_ast_dump_stack_t;
|
||||
|
||||
typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...);
|
||||
|
||||
typedef struct {
|
||||
scc_ast_dump_stack_t stack; ///< 每层是否为最后子节点
|
||||
cbool use_color; ///< 是否使用颜色输出
|
||||
|
||||
const char *vertical;
|
||||
const char *branch;
|
||||
const char *last_branch;
|
||||
const char *space;
|
||||
|
||||
const char *node_color; ///< 节点类型颜色
|
||||
const char *value_color; ///< 值颜色
|
||||
const char *branch_color; ///< 分支符号颜色
|
||||
const char *reset_color; ///< 重置颜色
|
||||
|
||||
scc_tree_dump_output_t output_func;
|
||||
void *output_userdata;
|
||||
} scc_tree_dump_ctx_t;
|
||||
|
||||
static inline void scc_tree_dump_ctx_init(scc_tree_dump_ctx_t *ctx,
|
||||
cbool use_color,
|
||||
scc_tree_dump_output_t output_func,
|
||||
void *output_userdata) {
|
||||
ctx->use_color = use_color;
|
||||
scc_vec_init(ctx->stack);
|
||||
|
||||
ctx->vertical = SCC_TREE_DUMP_VERTICAL;
|
||||
ctx->branch = SCC_TREE_DUMP_BRANCH;
|
||||
ctx->last_branch = SCC_TREE_DUMP_LAST_BRANCH;
|
||||
ctx->space = SCC_TREE_DUMP_SPACE;
|
||||
|
||||
ctx->node_color = use_color ? SCC_TREE_DUMP_NODE_COLOR : "";
|
||||
ctx->value_color = use_color ? SCC_TREE_DUMP_VALUE_COLOR : "";
|
||||
ctx->branch_color = use_color ? SCC_TREE_DUMP_BRANCH_COLOR : "";
|
||||
ctx->reset_color = use_color ? SCC_TREE_DUMP_RESET_COLOR : "";
|
||||
|
||||
ctx->output_func = output_func;
|
||||
ctx->output_userdata = output_userdata;
|
||||
}
|
||||
|
||||
#define scc_tree_dump_printf(ctx, fmt, ...) \
|
||||
(ctx)->output_func((ctx)->output_userdata, fmt, ##__VA_ARGS__)
|
||||
|
||||
static inline void scc_tree_dump_ctx_drop(scc_tree_dump_ctx_t *ctx) {
|
||||
scc_vec_free(ctx->stack);
|
||||
}
|
||||
|
||||
// 打印缩进
|
||||
static inline void scc_tree_print_indent(scc_tree_dump_ctx_t *ctx) {
|
||||
scc_vec_foreach(ctx->stack, i) {
|
||||
cbool last_child = scc_vec_at(ctx->stack, i);
|
||||
const char *data = null;
|
||||
if (i + 1 == scc_vec_size(ctx->stack)) {
|
||||
// 最后一层打印分支符号
|
||||
data = last_child ? ctx->last_branch : ctx->branch;
|
||||
} else {
|
||||
data = last_child ? ctx->space : ctx->vertical;
|
||||
}
|
||||
Assert(data != null);
|
||||
if (ctx->use_color) {
|
||||
ctx->output_func(ctx->output_userdata, "%s%s%s", ctx->branch_color,
|
||||
data, ctx->reset_color);
|
||||
} else {
|
||||
ctx->output_func(ctx->output_userdata, "%s", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define SCC_TREE_DUMP_PRINT_COLORED(ctx, color, before_str, fmt, after_str, \
|
||||
...) \
|
||||
(ctx)->output_func((ctx)->output_userdata, \
|
||||
before_str "%s" fmt "%s" after_str, \
|
||||
(ctx)->use_color ? color : "", ##__VA_ARGS__, \
|
||||
(ctx)->use_color ? ANSI_NONE : "");
|
||||
|
||||
#define SCC_TREE_DUMP_PRINT_AROUND(ctx, color, around_str, fmt, ...) \
|
||||
SCC_TREE_DUMP_PRINT_COLORED(ctx, color, around_str, fmt, around_str, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define SCC_TREE_DUMP_PRINT_PURE(ctx, color, fmt, ...) \
|
||||
SCC_TREE_DUMP_PRINT_COLORED(ctx, color, "", fmt, "", ##__VA_ARGS__)
|
||||
|
||||
// 推入新的层级到栈中
|
||||
static inline void scc_tree_dump_push_level(scc_tree_dump_ctx_t *ctx,
|
||||
cbool is_last_child) {
|
||||
scc_vec_push(ctx->stack, is_last_child);
|
||||
}
|
||||
|
||||
// 弹出当前层级
|
||||
static inline void scc_tree_dump_pop_level(scc_tree_dump_ctx_t *ctx) {
|
||||
(void)scc_vec_pop(ctx->stack);
|
||||
}
|
||||
|
||||
// 获取当前层级深度
|
||||
static inline usize scc_tree_dump_depth(scc_tree_dump_ctx_t *ctx) {
|
||||
return scc_vec_size(ctx->stack);
|
||||
}
|
||||
|
||||
#endif /* __SCC_TREE_DUMP_H__ */
|
||||
126
libs/tree_dump/src/scc_tree_dump.c
Normal file
126
libs/tree_dump/src/scc_tree_dump.c
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <scc_tree_dump.h>
|
||||
|
||||
#define DEFAULT_VERTICAL "| "
|
||||
#define DEFAULT_BRANCH "|-"
|
||||
#define DEFAULT_LAST_BRANCH "`-"
|
||||
#define DEFAULT_SPACE " "
|
||||
#define NODE_COLOR "\033[34m"
|
||||
#define VALUE_COLOR "\033[32m"
|
||||
#define BRANCH_COLOR "\033[33m"
|
||||
#define RESET_COLOR "\033[0m"
|
||||
|
||||
void scc_tree_dump_init(scc_tree_dump_t *td, cbool use_color) {
|
||||
scc_str_init(&td->buf);
|
||||
scc_vec_init(td->stack);
|
||||
td->use_color = use_color;
|
||||
td->line_start = true;
|
||||
|
||||
td->vertical = DEFAULT_VERTICAL;
|
||||
td->branch = DEFAULT_BRANCH;
|
||||
td->last_branch = DEFAULT_LAST_BRANCH;
|
||||
td->space = DEFAULT_SPACE;
|
||||
|
||||
td->node_color = use_color ? NODE_COLOR : "";
|
||||
td->value_color = use_color ? VALUE_COLOR : "";
|
||||
td->branch_color = use_color ? BRANCH_COLOR : "";
|
||||
td->reset_color = use_color ? RESET_COLOR : "";
|
||||
}
|
||||
|
||||
void scc_tree_dump_drop(scc_tree_dump_t *td) {
|
||||
scc_str_drop(&td->buf);
|
||||
scc_vec_free(td->stack);
|
||||
}
|
||||
|
||||
void scc_tree_dump_clear(scc_tree_dump_t *td) {
|
||||
scc_str_clear(&td->buf);
|
||||
td->line_start = true;
|
||||
}
|
||||
|
||||
const char *scc_tree_dump_cstr(scc_tree_dump_t *td) {
|
||||
return scc_str_as_cstr(&td->buf);
|
||||
}
|
||||
|
||||
void scc_tree_dump_flush(scc_tree_dump_t *td,
|
||||
void (*output)(const char *str, usize len, void *user),
|
||||
void *user) {
|
||||
if (td->buf.size > 1 && output) {
|
||||
output(td->buf.data, td->buf.size - 1, user);
|
||||
}
|
||||
scc_tree_dump_clear(td);
|
||||
}
|
||||
|
||||
void scc_tree_dump_begin_line(scc_tree_dump_t *td) {
|
||||
if (!td->line_start) {
|
||||
// 如果不在行首,先换行(表示上一行结束)
|
||||
if (td->buf.size > 1) {
|
||||
scc_str_append_ch(&td->buf, '\n');
|
||||
}
|
||||
}
|
||||
// 输出缩进
|
||||
usize depth = scc_vec_size(td->stack);
|
||||
for (usize i = 0; i < depth; i++) {
|
||||
cbool last = scc_vec_at(td->stack, i);
|
||||
const char *prefix;
|
||||
if (i + 1 == depth) {
|
||||
prefix = last ? td->last_branch : td->branch;
|
||||
} else {
|
||||
prefix = last ? td->space : td->vertical;
|
||||
}
|
||||
if (td->use_color) {
|
||||
scc_str_append_fmt(&td->buf, "%s%s%s", td->branch_color, prefix,
|
||||
td->reset_color);
|
||||
} else {
|
||||
scc_str_append_cstr(&td->buf, prefix, scc_strlen(prefix));
|
||||
}
|
||||
}
|
||||
td->line_start = false;
|
||||
}
|
||||
|
||||
void scc_tree_dump_append(scc_tree_dump_t *td, const char *s) {
|
||||
if (td->line_start) {
|
||||
scc_tree_dump_begin_line(td);
|
||||
}
|
||||
scc_str_append_cstr(&td->buf, s, scc_strlen(s));
|
||||
}
|
||||
|
||||
void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...) {
|
||||
if (td->line_start) {
|
||||
scc_tree_dump_begin_line(td);
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
// 计算所需长度
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
usize len = scc_vsnprintf(null, 0, fmt, args_copy);
|
||||
va_end(args_copy);
|
||||
if (len == 0) {
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
// 确保缓冲区容量足够
|
||||
if (td->buf.size + len + 1 > td->buf.cap) {
|
||||
usize new_cap = td->buf.cap;
|
||||
while (new_cap < td->buf.size + len + 1) {
|
||||
new_cap = new_cap ? new_cap * 2 : 16;
|
||||
}
|
||||
char *new_data = (char *)scc_realloc(td->buf.data, new_cap);
|
||||
Assert(new_data != null);
|
||||
td->buf.data = new_data;
|
||||
td->buf.cap = new_cap;
|
||||
}
|
||||
scc_vsnprintf(td->buf.data + td->buf.size - (td->buf.size == 0 ? 0 : 1),
|
||||
len + 1, fmt, args);
|
||||
va_end(args);
|
||||
if (td->buf.size == 0) {
|
||||
td->buf.size = 1;
|
||||
}
|
||||
td->buf.size += len;
|
||||
td->buf.data[td->buf.size - 1] = '\0';
|
||||
}
|
||||
|
||||
void scc_tree_dump_push(scc_tree_dump_t *td, cbool is_last) {
|
||||
scc_vec_push(td->stack, is_last);
|
||||
}
|
||||
|
||||
void scc_tree_dump_pop(scc_tree_dump_t *td) { (void)scc_vec_pop(td->stack); }
|
||||
Reference in New Issue
Block a user