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