Files
scc/libs/ast/include/scc_ast.h
zzy 4144f7841c refactor(argparse): 将null替换为nullptr以提高C++兼容性
- 在argparse库中将所有null指针常量替换为nullptr
- 更新头文件和源文件中的指针初始化和比较操作
- 修改测试文件中的相关断言检查
- 更新AST定义文件中的注释说明
2026-04-05 20:18:09 +08:00

601 lines
24 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_H__
#define __SCC_AST_H__
#include "ast_def.h"
#include "ast_dump.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_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_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_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_type_t *type,
const char *name, 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;
}
static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
scc_ast_node_type_t type,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != nullptr);
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_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_type_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_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_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_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_type_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_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;
}
// have defined builtin type
static inline void scc_ast_type_builtin_init(scc_ast_type_t *type,
scc_ast_builtin_type_t builtin,
scc_pos_t loc) {
Assert(type != nullptr);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_BUILTIN;
type->builtin.type = builtin;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
}
static inline void scc_ast_type_pointer_init(scc_ast_type_t *type,
scc_ast_type_t *pointee,
scc_pos_t loc) {
Assert(type != nullptr && pointee != nullptr);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_POINTER;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->pointer.pointee = pointee;
}
// size can be nullptr
static inline void scc_ast_type_array_init(scc_ast_type_t *type,
scc_ast_type_t *element,
scc_ast_expr_t *size,
scc_pos_t loc) {
Assert(type != nullptr && element != nullptr);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_ARRAY;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->array.element = element;
type->array.size = size;
}
// return_type and params can be nullptr
static inline void scc_ast_type_function_init(scc_ast_type_t *type,
scc_ast_type_t *return_type,
scc_ast_decl_vec_t *params,
scc_pos_t loc) {
Assert(type != nullptr);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_FUNCTION;
type->function.return_type = return_type;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
if (params == nullptr) {
scc_vec_init(type->function.params);
} else {
type->function.params = *params;
scc_vec_init(*params);
}
}
static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
scc_ast_node_type_t type_kind,
const char *name,
scc_ast_decl_t *decl,
scc_pos_t loc) {
Assert(type != nullptr);
type->base.loc = loc;
type->base.type = type_kind;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->record.name = name;
type->record.decl = decl;
}
// name and decl can be nullptr
static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *decl,
scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl, loc);
}
// name and decl can be nullptr
static inline void scc_ast_type_union_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *decl,
scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl, loc);
}
// name and decl can be nullptr
static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *decl, scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_ENUM, name, decl, loc);
}
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *target,
scc_pos_t loc) {
Assert(type != nullptr && target != nullptr);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_TYPEDEF;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->typedef_type.name = name;
type->typedef_type.decl = target;
}
#endif /* __SCC_AST_H__ */