refactor(ast): 将AST类型系统重构为规范类型系统

- 将scc_ast_type_t替换为scc_ast_qual_type_t,引入规范类型概念
- 添加scc_ast_canonical_type_t联合体用于表示规范类型
- 修改头文件结构,移除大量内联初始化函数,改为使用AST上下文分配器
- 添加SCC_AST_ALLOC宏用于统一节点分配管理
- 更新builtin类型枚举定义,添加类型计数常量

feat(ast): 引入AST上下文管理器

- 创建scc_ast_ctx_t结构体用于管理AST节点生命周期
- 实现类型池化机制,支持内置类型的统一管理
- 添加canonical类型获取和分配接口

refactor(abi): 适配新的AST类型系统

- 更新头文件包含,从<scc_ir.h>改为<scc_hir.h>
- 适配函数参数类型,使用qual_type替代原始type
- 使用scc_ast_canon_type()函数获取规范类型进行处理

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
zzy
2026-04-27 20:40:03 +08:00
parent d7ac5fd30b
commit f6bc40ae4a
20 changed files with 1302 additions and 1045 deletions

View File

@@ -1,13 +1,59 @@
#include <scc_ast_utils.h>
#include <scc_pos_log.h>
#include <scc_sema.h>
#include <sema_symtab.h>
static const scc_ast_qual_type_t *got_type_callback(void *context,
const char *name);
static void gen_symbol_name(const scc_ast_decl_t *decl, scc_str_t *name) {
switch (decl->base.type) {
case SCC_AST_TYPE_ENUM:
*name = scc_str_from_cstr("$E_");
scc_str_append_cstr(name, decl->name, scc_strlen(decl->name));
break;
case SCC_AST_TYPE_STRUCT:
*name = scc_str_from_cstr("$S_");
scc_str_append_cstr(name, decl->name, scc_strlen(decl->name));
break;
case SCC_AST_TYPE_UNION:
*name = scc_str_from_cstr("$U_");
scc_str_append_cstr(name, decl->name, scc_strlen(decl->name));
break;
default:
break;
}
}
static void symtab_add_symbol(scc_sema_symtab_t *sema_symtab,
scc_ast_decl_t *decl,
scc_ast_node_t *ast_node_ref) {
if (decl->name == nullptr)
return;
// FIXME memory leak
scc_str_t name = scc_str_empty();
gen_symbol_name(decl, &name);
if (scc_str_is_empty(&name)) {
scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref);
} else {
scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name),
ast_node_ref);
}
}
static void type_callback(void *context, scc_ast_node_kind_t node_type,
void *node) {
scc_sema_symtab_t *sema_symtab = context;
(void)context;
(void)node_type;
(void)node;
scc_ast_qual_type_t *type = SCC_AST_CAST_TO(scc_ast_qual_type_t, node);
if (node_type == SCC_AST_TYPE_STRUCT) {
symtab_add_symbol(sema_symtab, type->type->record.decl, &type->base);
} else if (node_type == SCC_AST_TYPE_UNION) {
symtab_add_symbol(sema_symtab, type->type->record.decl, &type->base);
} else if (node_type == SCC_AST_TYPE_ENUM) {
symtab_add_symbol(sema_symtab, type->type->record.decl, &type->base);
}
return;
}
@@ -71,119 +117,83 @@ static void decl_callback(void *context, scc_ast_node_kind_t node_type,
}
scc_ast_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
Assert(type != nullptr);
if (node_type == SCC_AST_DECL_STRUCT) {
scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc);
// FIXME memory leak
scc_str_t name = scc_str_from_cstr("$S_");
if (decl->name == nullptr) {
decl->name = "<anonymous struct>";
}
scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name),
&type->base);
} else if (node_type == SCC_AST_DECL_UNION) {
scc_ast_type_union_init(type, decl->name, decl, decl->base.loc);
scc_str_t name = scc_str_from_cstr("$U_");
if (decl->name == nullptr) {
decl->name = "<anonymous union>";
}
scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name),
&type->base);
} else if (node_type == SCC_AST_DECL_ENUM) {
scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc);
scc_str_t name = scc_str_from_cstr("$E_");
if (decl->name == nullptr) {
decl->name = "<anonymous enum>";
}
scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name),
&type->base);
scc_vec_foreach(decl->record.fields, i) {
scc_ast_decl_t *enum_decl = scc_vec_at(decl->record.fields, i);
scc_sema_symtab_add_symbol(sema_symtab, enum_decl->name,
&enum_decl->base);
// LOG_INFO("enum added %s", enum_decl->name);
}
} else if (node_type == SCC_AST_DECL_TYPEDEF) {
if (node_type == SCC_AST_DECL_TYPEDEF) {
if (decl->name == nullptr) {
SCC_ERROR(decl->base.loc, "typedef without name");
return;
}
scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc);
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
symtab_add_symbol(sema_symtab, decl, &decl->typedef_decl.type->base);
} else if (node_type == SCC_AST_DECL_VAR) {
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
symtab_add_symbol(sema_symtab, decl, &decl->base);
} else if (node_type == SCC_AST_DECL_PARAM) {
if (decl->name == nullptr) {
if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN &&
(decl->param.type->builtin.type ==
(decl->param.type->type->builtin.type ==
SCC_AST_BUILTIN_TYPE_VA_LIST ||
decl->param.type->builtin.type == SCC_AST_BUILTIN_TYPE_VOID)) {
decl->param.type->type->builtin.type ==
SCC_AST_BUILTIN_TYPE_VOID)) {
return;
}
SCC_ERROR(decl->base.loc, "sema error: Parameter must have a name");
return;
}
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
symtab_add_symbol(sema_symtab, decl, &decl->base);
} else if (node_type == SCC_AST_DECL_FUNC) {
if (decl->name == nullptr) {
SCC_ERROR(decl->base.loc, "sema error: Function must have a name");
} else {
// FIXME 重名函数...
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
symtab_add_symbol(sema_symtab, decl, &decl->base);
}
}
return;
}
static scc_ast_type_t *got_type_callback(void *context, const char *name) {
static const scc_ast_qual_type_t *got_type_callback(void *context,
const char *name) {
scc_sema_symtab_t *sema_symtab = context;
scc_ast_node_t *node = scc_sema_symtab_lookup_symbol(sema_symtab, name);
if (SCC_AST_IS_A(scc_ast_type_t, node)) {
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
*type = *(scc_ast_type_t *)node;
return type;
if (SCC_AST_IS_A(scc_ast_qual_type_t, node)) {
return (scc_ast_qual_type_t *)node;
}
return nullptr;
}
void scc_sema_init(scc_sema_callbacks_t *callbacks) {
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx) {
sema_ctx->ast_ctx = ast_ctx;
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
if (sema_symtab == nullptr) {
LOG_FATAL("out of memory");
return;
}
callbacks->context = sema_symtab;
callbacks->on_decl = decl_callback;
callbacks->on_expr = expr_callback;
callbacks->on_stmt = stmt_callback;
callbacks->on_type = type_callback;
callbacks->got_type = got_type_callback;
sema_ctx->context = sema_symtab;
sema_ctx->on_decl = decl_callback;
sema_ctx->on_expr = expr_callback;
sema_ctx->on_stmt = stmt_callback;
sema_ctx->on_type = type_callback;
sema_ctx->got_type = got_type_callback;
scc_sema_symtab_init(sema_symtab);
// FIXME memory leak
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST,
scc_pos_create());
scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_ctx);
scc_ast_type_builtin_init(type, sema_ctx->ast_ctx,
SCC_AST_BUILTIN_TYPE_VA_LIST, scc_pos_create());
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list",
&type->base);
scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(sema_ctx->ast_ctx);
scc_ast_decl_val_init(decl, type, "__scc_builtin__", nullptr,
scc_pos_create());
scc_sema_symtab_add_symbol(sema_symtab, "__func__", &decl->base);
scc_ast_type_t *built_func_type = scc_malloc(sizeof(scc_ast_type_t));
scc_ast_type_function_init(built_func_type, nullptr, nullptr,
scc_pos_create());
scc_ast_decl_t *builin_func = scc_malloc(sizeof(scc_ast_decl_t));
scc_ast_qual_type_t *built_func_type =
SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_ctx);
// FIXME hack
built_func_type->base.type = SCC_AST_TYPE_FUNCTION;
scc_ast_decl_t *builin_func = SCC_AST_ALLOC_DECL(sema_ctx->ast_ctx);
scc_ast_decl_func_init(builin_func, built_func_type, "__scc_builtin_func",
nullptr, scc_pos_create());
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_start",
@@ -196,9 +206,9 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
&builin_func->base);
}
void scc_sema_drop(scc_sema_callbacks_t *callbacks) {
void scc_sema_drop(scc_sema_ctx_t *sema_ctx) {
// FIXME drop obj
if (callbacks->context) {
scc_sema_symtab_drop(callbacks->context);
if (sema_ctx->context) {
scc_sema_symtab_drop(sema_ctx->context);
}
}