Files
scc/libs/ast/include/scc_ast_utils.h
zzy f6bc40ae4a 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>
2026-04-27 20:40:03 +08:00

506 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __SCC_AST_UTILS_H__
#define __SCC_AST_UTILS_H__
#include "scc_ast_def.h"
// decls can be nullptr but maybe warning
static inline void
scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
scc_ast_decl_vec_t *decls, scc_pos_t loc) {
Assert(translation_unit != nullptr);
translation_unit->base.type = SCC_AST_TRANSLATION_UNIT;
translation_unit->base.loc = loc;
if (decls == nullptr) {
scc_vec_init(translation_unit->declarations);
} else {
translation_unit->declarations = *decls;
scc_vec_init(*decls);
}
}
static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl,
scc_ast_decl_vec_t *list_move,
scc_pos_t loc) {
Assert(decl != nullptr && list_move != nullptr);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_LIST;
decl->name = nullptr;
decl->list.vars = *list_move;
scc_vec_init(*list_move);
}
// name and var_init can be nullptr
static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
scc_ast_qual_type_t *type,
const char *name,
scc_ast_expr_t *var_init,
scc_pos_t loc) {
Assert(decl != nullptr && type != nullptr);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_VAR;
decl->name = name;
decl->var.type = type;
decl->var.init = var_init;
}
// var_init can be nullptr
static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
scc_ast_qual_type_t *type,
const char *name,
scc_ast_expr_t *var_init,
scc_pos_t loc) {
Assert(decl != nullptr && name != nullptr && type != nullptr);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_VAR;
decl->name = name;
decl->var.type = type;
decl->var.init = var_init;
}
// body can be nullptr
static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
scc_ast_qual_type_t *type,
const char *name,
scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(decl != nullptr && name != nullptr && type != nullptr);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_FUNC;
decl->name = name;
decl->func.type = type;
Assert(type->base.type == SCC_AST_TYPE_FUNCTION);
decl->func.body = body;
}
// name can be nullptr
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
scc_ast_qual_type_t *type,
const char *name, int idx,
scc_pos_t loc) {
Assert(decl != nullptr && type != nullptr);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_PARAM;
decl->name = name;
decl->param.type = type;
decl->param.param_idx = idx;
}
static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
scc_ast_node_kind_t type,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != nullptr);
if (name == nullptr) {
name = "<anonymous>";
}
decl->base.loc = loc;
decl->base.type = type;
decl->name = name;
if (fields_move == nullptr) {
scc_vec_init(decl->record.fields);
} else {
decl->record.fields = *fields_move;
scc_vec_init(*fields_move);
}
}
// name and fields can be nullptr
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
_scc_ast_decl_record_init(decl, SCC_AST_DECL_STRUCT, name, fields_move,
loc);
}
// name and fields can be nullptr
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
_scc_ast_decl_record_init(decl, SCC_AST_DECL_UNION, name, fields_move, loc);
}
// name and fields can be nullptr
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
_scc_ast_decl_record_init(decl, SCC_AST_DECL_ENUM, name, fields_move, loc);
}
static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_qual_type_t *type,
scc_pos_t loc) {
Assert(decl != nullptr && name != nullptr && type != nullptr);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_TYPEDEF;
decl->name = name;
decl->typedef_decl.type = type;
}
// items can be nullptr
static inline void scc_ast_stmt_compound_init(
scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) {
Assert(stmt != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_COMPOUND;
if (items_move == nullptr) {
scc_vec_init(stmt->compound.block_items);
} else {
stmt->compound.block_items = *items_move;
scc_vec_init(*items_move);
}
}
// expr can be nullptr
static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *expr, scc_pos_t loc) {
Assert(stmt != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_EXPR;
stmt->expr.expr = expr;
}
// opt_else can be nullptr
static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *then,
scc_ast_stmt_t *opt_else,
scc_pos_t loc) {
Assert(stmt != nullptr && cond != nullptr && then != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_IF;
stmt->if_stmt.cond = cond;
stmt->if_stmt.then_stmt = then;
stmt->if_stmt.opt_else_stmt = opt_else;
}
static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_WHILE;
stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body;
}
static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_DO_WHILE;
stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body;
}
// FIXME
static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt,
scc_ast_node_t *init,
scc_ast_expr_t *cond,
scc_ast_expr_t *incr,
scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(stmt != nullptr && body != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_FOR;
stmt->for_stmt.init = init;
stmt->for_stmt.cond = cond;
stmt->for_stmt.incr = incr;
stmt->for_stmt.body = body;
}
static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_SWITCH;
stmt->switch_stmt.cond = cond;
stmt->switch_stmt.body = body;
}
static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_CASE;
stmt->case_stmt.expr = cond;
stmt->case_stmt.stmt = body;
}
static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != nullptr && body != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_DEFAULT;
stmt->default_stmt.stmt = body;
}
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt,
scc_pos_t loc) {
Assert(stmt != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_BREAK;
stmt->jump._target = nullptr;
}
static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt,
scc_pos_t loc) {
Assert(stmt != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_CONTINUE;
stmt->jump._target = nullptr;
}
// expr can be nullptr
static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *expr,
scc_pos_t loc) {
Assert(stmt != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_RETURN;
stmt->return_stmt.expr = expr;
}
static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt,
const char *label, scc_pos_t loc) {
Assert(stmt != nullptr && label != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_GOTO;
stmt->goto_stmt.label = label;
stmt->goto_stmt._target = nullptr;
}
static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
const char *label,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != nullptr);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_LABEL;
stmt->label_stmt.label = label;
stmt->label_stmt.stmt = body;
}
static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op,
scc_ast_expr_t *lhs,
scc_ast_expr_t *rhs,
scc_pos_t loc) {
Assert(expr != nullptr && lhs != nullptr && rhs != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_BINARY;
expr->binary.op = op;
expr->binary.lhs = lhs;
expr->binary.rhs = rhs;
}
static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op,
scc_ast_expr_t *operand,
scc_pos_t loc) {
Assert(expr != nullptr && operand != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_UNARY;
expr->unary.op = op;
expr->unary.operand = operand;
}
static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
scc_ast_expr_t *cond,
scc_ast_expr_t *then_expr,
scc_ast_expr_t *else_expr,
scc_pos_t loc) {
Assert(expr != nullptr && cond != nullptr && then_expr != nullptr &&
else_expr != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_COND;
expr->cond.cond = cond;
expr->cond.then_expr = then_expr;
expr->cond.else_expr = else_expr;
}
// args can be nullptr
static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
scc_ast_expr_t *callee,
scc_ast_expr_vec_t *args,
scc_pos_t loc) {
Assert(expr != nullptr && callee != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_CALL;
expr->call.callee = callee;
if (args == nullptr) {
scc_vec_init(expr->call.args);
} else {
expr->call.args = *args;
}
}
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
scc_ast_expr_t *array,
scc_ast_expr_t *index,
scc_pos_t loc) {
Assert(expr != nullptr && array != nullptr && index != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT;
expr->subscript.array = array;
expr->subscript.index = index;
}
static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_node_kind_t type,
scc_ast_expr_t *object,
const char *member,
scc_pos_t loc) {
Assert(expr != nullptr && object != nullptr && member != nullptr);
expr->base.loc = loc;
expr->base.type = type;
expr->member.base = object;
expr->member.name = member;
expr->member._target_idx = 0;
}
static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object,
const char *member, scc_pos_t loc) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member, loc);
}
static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object,
const char *member,
scc_pos_t loc) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member,
loc);
}
static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
scc_ast_qual_type_t *type,
scc_ast_expr_t *operand,
scc_pos_t loc) {
Assert(expr != nullptr && type != nullptr && operand != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_CAST;
expr->cast.type = type;
expr->cast.expr = operand;
}
// type and target_expr can be nullptr but it only one of them can be nullptr
static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
scc_ast_qual_type_t *type,
scc_ast_expr_t *target_expr,
scc_pos_t loc) {
Assert(expr != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_SIZE_OF;
expr->attr_of.type = type;
expr->attr_of.expr = target_expr;
}
// type and target_expr can be nullptr but it only one of them can be nullptr
static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
scc_ast_qual_type_t *type,
scc_ast_expr_t *target_expr,
scc_pos_t loc) {
Assert(expr != nullptr);
expr->base.loc = loc;
expr->base.type =
SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF可能需要改为 ALIGN_OF
expr->attr_of.type = type;
expr->attr_of.expr = target_expr;
}
// lhs_exprs and rhs_exprs can be nullptr
static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
scc_ast_expr_t *base,
scc_ast_expr_vec_t *lhs_exprs,
scc_ast_expr_vec_t *rhs_exprs,
scc_pos_t loc) {
Assert(expr != nullptr && base != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_COMPOUND;
expr->compound.base = base;
if (lhs_exprs == nullptr) {
scc_vec_init(expr->compound.lhs_exprs);
} else {
expr->compound.lhs_exprs = *lhs_exprs;
scc_vec_init(*lhs_exprs);
}
if (rhs_exprs == nullptr) {
scc_vec_init(expr->compound.rhs_exprs);
} else {
expr->compound.rhs_exprs = *rhs_exprs;
scc_vec_init(*rhs_exprs);
}
}
static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
scc_ast_node_kind_t type,
const char *value, cbool owned,
scc_pos_t loc) {
Assert(expr != nullptr && value != nullptr);
expr->base.loc = loc;
expr->base.type = type;
expr->literal.lexme = value;
expr->literal.owned = owned;
}
static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr,
const char *value, cbool owned,
scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr,
const char *value,
cbool owned, scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr,
const char *value,
cbool owned, scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr,
const char *value,
cbool owned,
scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
const char *name,
scc_pos_t loc) {
Assert(expr != nullptr && name != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_IDENTIFIER;
expr->identifier.name = name;
expr->identifier._target = nullptr;
}
static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr,
scc_ast_qual_type_t *type,
scc_pos_t loc) {
Assert(expr != nullptr && type != nullptr);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_LVALUE;
expr->lvalue.type = type;
}
#endif /* __SCC_AST_UTILS_H__ */