#ifndef __SCC_AST_H__ #define __SCC_AST_H__ #include "ast_def.h" #include "ast_dump.h" // decls can be null 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 != null); translation_unit->base.type = SCC_AST_TRANSLATION_UNIT; translation_unit->base.loc = loc; if (decls == null) { 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 != null && list_move != null); decl->base.loc = loc; decl->base.type = SCC_AST_DECL_LIST; decl->name = null; decl->list.vars = *list_move; scc_vec_init(*list_move); } // name and var_init can be null 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 != null && type != null); 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 null 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 != null && name != null && type != null); 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 null 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 != null && name != null && type != null); 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 null 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 != null && type != null); 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 != null); decl->base.loc = loc; decl->base.type = type; decl->name = name; if (fields_move == null) { scc_vec_init(decl->record.fields); } else { decl->record.fields = *fields_move; scc_vec_init(*fields_move); } } // name and fields can be null 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 null 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 null 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 != null && name != null && type != null); decl->base.loc = loc; decl->base.type = SCC_AST_DECL_TYPEDEF; decl->name = name; decl->typedef_decl.type = type; } // items can be null 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 != null); stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_COMPOUND; if (items_move == null) { scc_vec_init(stmt->compound.block_items); } else { stmt->compound.block_items = *items_move; scc_vec_init(*items_move); } } // expr can be null static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt, scc_ast_expr_t *expr, scc_pos_t loc) { Assert(stmt != null); stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_EXPR; stmt->expr.expr = expr; } // opt_else can be null 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 != null && cond != null && then != null); 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 != null && cond != null && body != null); 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 != null && cond != null && body != null); 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 != null && body != null); 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 != null && cond != null && body != null); 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 != null && cond != null && body != null); 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 != null && body != null); 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 != null); stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_BREAK; stmt->jump._target = null; } static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt, scc_pos_t loc) { Assert(stmt != null); stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_CONTINUE; stmt->jump._target = null; } // expr can be null static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt, scc_ast_expr_t *expr, scc_pos_t loc) { Assert(stmt != null); 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 != null && label != null); stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_GOTO; stmt->goto_stmt.label = label; stmt->goto_stmt._target = null; } 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 != null); 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 != null && lhs != null && rhs != null); 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 != null && operand != null); 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 != null && cond != null && then_expr != null && else_expr != null); 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 null 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 != null && callee != null); expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_CALL; expr->call.callee = callee; if (args == null) { 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 != null && array != null && index != null); 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 != null && object != null && member != null); 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 != null && type != null && operand != null); 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 null but it only one of them can be null 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 != null); 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 null but it only one of them can be null 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 != null); 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 null 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 != null && base != null); expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_COMPOUND; expr->compound.base = base; if (lhs_exprs == null) { scc_vec_init(expr->compound.lhs_exprs); } else { expr->compound.lhs_exprs = *lhs_exprs; scc_vec_init(*lhs_exprs); } if (rhs_exprs == null) { 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 != null && value != null); 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 != null && name != null); expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_IDENTIFIER; expr->identifier.name = name; expr->identifier._target = null; } static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, scc_ast_type_t *type, scc_pos_t loc) { Assert(expr != null && type != null); 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 != null); 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 != null && pointee != null); 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 null 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 != null && element != null); 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 null 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 != null); 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 == null) { 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 != null); 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 null 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 null 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 null 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 != null && target != null); 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__ */