diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-01-23 22:00:27 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-01-23 22:02:59 +0900 |
| commit | 52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5 (patch) | |
| tree | 410ba8352f1e3af62c86c537328dcd9504613d61 | |
| parent | 7838acf484f7cb64b7723f2a1dd2fe00f53b77fc (diff) | |
| download | ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.tar.gz ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.tar.zst ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.zip | |
refactor: AST overhaul
| -rw-r--r-- | src/ast.c | 298 | ||||
| -rw-r--r-- | src/ast.h | 273 | ||||
| -rw-r--r-- | src/codegen.c | 386 | ||||
| -rw-r--r-- | src/codegen_wasm.c | 82 | ||||
| -rw-r--r-- | src/parse.c | 484 |
5 files changed, 943 insertions, 580 deletions
@@ -75,7 +75,11 @@ const char* type_kind_stringify(TypeKind k) { } static AstNode* members_of(Type* ty) { - return ty->ref.defs->node_items[ty->ref.index].node_members; + AstNode* def = &ty->ref.defs->as.list->items[ty->ref.index]; + if (def->kind == AstNodeKind_struct_def) + return def->as.struct_def->members; + else + return def->as.union_def->members; } Type* type_new(TypeKind kind) { @@ -287,9 +291,10 @@ AstNode* ast_new_list(int capacity) { if (capacity == 0) unreachable(); AstNode* list = ast_new(AstNodeKind_list); - list->node_cap = capacity; - list->node_len = 0; - list->node_items = calloc(list->node_cap, sizeof(AstNode)); + list->as.list = calloc(1, sizeof(ListNode)); + list->as.list->cap = capacity; + list->as.list->len = 0; + list->as.list->items = calloc(list->as.list->cap, sizeof(AstNode)); return list; } @@ -300,35 +305,39 @@ void ast_append(AstNode* list, AstNode* item) { if (!item) { return; } - if (list->node_cap <= list->node_len) { - list->node_cap *= 2; - list->node_items = realloc(list->node_items, sizeof(AstNode) * list->node_cap); - memset(list->node_items + list->node_len, 0, sizeof(AstNode) * (list->node_cap - list->node_len)); + if (list->as.list->cap <= list->as.list->len) { + list->as.list->cap *= 2; + list->as.list->items = realloc(list->as.list->items, sizeof(AstNode) * list->as.list->cap); + memset(list->as.list->items + list->as.list->len, 0, + sizeof(AstNode) * (list->as.list->cap - list->as.list->len)); } - memcpy(list->node_items + list->node_len, item, sizeof(AstNode)); - ++list->node_len; + memcpy(list->as.list->items + list->as.list->len, item, sizeof(AstNode)); + ++list->as.list->len; } AstNode* ast_new_int(int v) { AstNode* e = ast_new(AstNodeKind_int_expr); - e->node_int_value = v; + e->as.int_expr = calloc(1, sizeof(IntExprNode)); + e->as.int_expr->value = v; e->ty = type_new(TypeKind_int); return e; } AstNode* ast_new_unary_expr(int op, AstNode* operand) { AstNode* e = ast_new(AstNodeKind_unary_expr); - e->node_op = op; - e->node_operand = operand; + e->as.unary_expr = calloc(1, sizeof(UnaryExprNode)); + e->as.unary_expr->op = op; + e->as.unary_expr->operand = operand; e->ty = type_new(TypeKind_int); return e; } AstNode* ast_new_binary_expr(int op, AstNode* lhs, AstNode* rhs) { AstNode* e = ast_new(AstNodeKind_binary_expr); - e->node_op = op; - e->node_lhs = lhs; - e->node_rhs = rhs; + e->as.binary_expr = calloc(1, sizeof(BinaryExprNode)); + e->as.binary_expr->op = op; + e->as.binary_expr->lhs = lhs; + e->as.binary_expr->rhs = rhs; if (op == TokenKind_plus) { if (lhs->ty->kind == TypeKind_ptr) { e->ty = lhs->ty; @@ -357,9 +366,10 @@ AstNode* ast_new_binary_expr(int op, AstNode* lhs, AstNode* rhs) { AstNode* ast_new_assign_expr(int op, AstNode* lhs, AstNode* rhs) { AstNode* e = ast_new(AstNodeKind_assign_expr); - e->node_op = op; - e->node_lhs = lhs; - e->node_rhs = rhs; + e->as.assign_expr = calloc(1, sizeof(AssignExprNode)); + e->as.assign_expr->op = op; + e->as.assign_expr->lhs = lhs; + e->as.assign_expr->rhs = rhs; e->ty = lhs->ty; return e; } @@ -382,39 +392,251 @@ AstNode* ast_new_assign_sub_expr(AstNode* lhs, AstNode* rhs) { AstNode* ast_new_ref_expr(AstNode* operand) { AstNode* e = ast_new(AstNodeKind_ref_expr); - e->node_operand = operand; + e->as.ref_expr = calloc(1, sizeof(RefExprNode)); + e->as.ref_expr->operand = operand; e->ty = type_new_ptr(operand->ty); return e; } AstNode* ast_new_deref_expr(AstNode* operand) { AstNode* e = ast_new(AstNodeKind_deref_expr); - e->node_operand = operand; + e->as.deref_expr = calloc(1, sizeof(DerefExprNode)); + e->as.deref_expr->operand = operand; e->ty = operand->ty->base; return e; } AstNode* ast_new_member_access_expr(AstNode* obj, const char* name) { AstNode* e = ast_new(AstNodeKind_deref_expr); - e->node_operand = ast_new_binary_expr(TokenKind_plus, obj, ast_new_int(type_offsetof(obj->ty->base, name))); + e->as.deref_expr = calloc(1, sizeof(DerefExprNode)); + e->as.deref_expr->operand = + ast_new_binary_expr(TokenKind_plus, obj, ast_new_int(type_offsetof(obj->ty->base, name))); e->ty = type_member_typeof(obj->ty->base, name); - e->node_operand->ty = type_new_ptr(e->ty); + e->as.deref_expr->operand->ty = type_new_ptr(e->ty); return e; } AstNode* ast_new_cast_expr(AstNode* operand, Type* result_ty) { AstNode* e = ast_new(AstNodeKind_cast_expr); - e->node_operand = operand; + e->as.cast_expr = calloc(1, sizeof(CastExprNode)); + e->as.cast_expr->operand = operand; e->ty = result_ty; return e; } +AstNode* ast_new_logical_expr(int op, AstNode* lhs, AstNode* rhs) { + AstNode* e = ast_new(AstNodeKind_logical_expr); + e->as.logical_expr = calloc(1, sizeof(LogicalExprNode)); + e->as.logical_expr->op = op; + e->as.logical_expr->lhs = lhs; + e->as.logical_expr->rhs = rhs; + e->ty = type_new(TypeKind_int); + return e; +} + +AstNode* ast_new_cond_expr(AstNode* cond, AstNode* then, AstNode* else_) { + AstNode* e = ast_new(AstNodeKind_cond_expr); + e->as.cond_expr = calloc(1, sizeof(CondExprNode)); + e->as.cond_expr->cond = cond; + e->as.cond_expr->then = then; + e->as.cond_expr->else_ = else_; + e->ty = then->ty; + return e; +} + +AstNode* ast_new_str_expr(int idx, Type* ty) { + AstNode* e = ast_new(AstNodeKind_str_expr); + e->as.str_expr = calloc(1, sizeof(StrExprNode)); + e->as.str_expr->idx = idx; + e->ty = ty; + return e; +} + +AstNode* ast_new_func_call(const char* name, Type* ty) { + AstNode* e = ast_new(AstNodeKind_func_call); + e->as.func_call = calloc(1, sizeof(FuncCallNode)); + e->as.func_call->name = name; + e->ty = ty; + return e; +} + +AstNode* ast_new_func(const char* name, Type* ty) { + AstNode* e = ast_new(AstNodeKind_func); + e->as.func = calloc(1, sizeof(FuncNode)); + e->as.func->name = name; + e->ty = ty; + return e; +} + +AstNode* ast_new_gvar(const char* name, Type* ty) { + AstNode* e = ast_new(AstNodeKind_gvar); + e->as.gvar = calloc(1, sizeof(GvarNode)); + e->as.gvar->name = name; + e->ty = ty; + return e; +} + +AstNode* ast_new_lvar(const char* name, int stack_offset, Type* ty) { + AstNode* e = ast_new(AstNodeKind_lvar); + e->as.lvar = calloc(1, sizeof(LvarNode)); + e->as.lvar->name = name; + e->as.lvar->stack_offset = stack_offset; + e->ty = ty; + return e; +} + +AstNode* ast_new_nop(void) { + return ast_new(AstNodeKind_nop); +} + +AstNode* ast_new_break_stmt(void) { + return ast_new(AstNodeKind_break_stmt); +} + +AstNode* ast_new_continue_stmt(void) { + return ast_new(AstNodeKind_continue_stmt); +} + +AstNode* ast_new_return_stmt(AstNode* expr) { + AstNode* e = ast_new(AstNodeKind_return_stmt); + e->as.return_stmt = calloc(1, sizeof(ReturnStmtNode)); + e->as.return_stmt->expr = expr; + return e; +} + +AstNode* ast_new_expr_stmt(AstNode* expr) { + AstNode* e = ast_new(AstNodeKind_expr_stmt); + e->as.expr_stmt = calloc(1, sizeof(ExprStmtNode)); + e->as.expr_stmt->expr = expr; + return e; +} + +AstNode* ast_new_if_stmt(AstNode* cond, AstNode* then, AstNode* else_) { + AstNode* e = ast_new(AstNodeKind_if_stmt); + e->as.if_stmt = calloc(1, sizeof(IfStmtNode)); + e->as.if_stmt->cond = cond; + e->as.if_stmt->then = then; + e->as.if_stmt->else_ = else_; + return e; +} + +AstNode* ast_new_for_stmt(AstNode* init, AstNode* cond, AstNode* update, AstNode* body) { + AstNode* e = ast_new(AstNodeKind_for_stmt); + e->as.for_stmt = calloc(1, sizeof(ForStmtNode)); + e->as.for_stmt->init = init; + e->as.for_stmt->cond = cond; + e->as.for_stmt->update = update; + e->as.for_stmt->body = body; + return e; +} + +AstNode* ast_new_do_while_stmt(AstNode* cond, AstNode* body) { + AstNode* e = ast_new(AstNodeKind_do_while_stmt); + e->as.do_while_stmt = calloc(1, sizeof(DoWhileStmtNode)); + e->as.do_while_stmt->cond = cond; + e->as.do_while_stmt->body = body; + return e; +} + +AstNode* ast_new_switch_stmt(AstNode* expr) { + AstNode* e = ast_new(AstNodeKind_switch_stmt); + e->as.switch_stmt = calloc(1, sizeof(SwitchStmtNode)); + e->as.switch_stmt->expr = expr; + return e; +} + +AstNode* ast_new_case_label(int value, AstNode* body) { + AstNode* e = ast_new(AstNodeKind_case_label); + e->as.case_label = calloc(1, sizeof(CaseLabelNode)); + e->as.case_label->value = value; + e->as.case_label->body = body; + return e; +} + +AstNode* ast_new_default_label(AstNode* body) { + AstNode* e = ast_new(AstNodeKind_default_label); + e->as.default_label = calloc(1, sizeof(DefaultLabelNode)); + e->as.default_label->body = body; + return e; +} + +AstNode* ast_new_goto_stmt(const char* label) { + AstNode* e = ast_new(AstNodeKind_goto_stmt); + e->as.goto_stmt = calloc(1, sizeof(GotoStmtNode)); + e->as.goto_stmt->label = label; + return e; +} + +AstNode* ast_new_label_stmt(const char* name, AstNode* body) { + AstNode* e = ast_new(AstNodeKind_label_stmt); + e->as.label_stmt = calloc(1, sizeof(LabelStmtNode)); + e->as.label_stmt->name = name; + e->as.label_stmt->body = body; + return e; +} + +AstNode* ast_new_declarator(const char* name, Type* ty) { + AstNode* e = ast_new(AstNodeKind_declarator); + e->as.declarator = calloc(1, sizeof(DeclaratorNode)); + e->as.declarator->name = name; + e->ty = ty; + return e; +} + +AstNode* ast_new_func_def(const char* name, Type* ty, AstNode* params, AstNode* body, int stack_size) { + AstNode* e = ast_new(AstNodeKind_func_def); + e->as.func_def = calloc(1, sizeof(FuncDefNode)); + e->as.func_def->name = name; + e->as.func_def->params = params; + e->as.func_def->body = body; + e->as.func_def->stack_size = stack_size; + e->ty = ty; + return e; +} + +AstNode* ast_new_enum_member(const char* name, int value) { + AstNode* e = ast_new(AstNodeKind_enum_member); + e->as.enum_member = calloc(1, sizeof(EnumMemberNode)); + e->as.enum_member->name = name; + e->as.enum_member->value = value; + return e; +} + +AstNode* ast_new_typedef_decl(const char* name, Type* ty) { + AstNode* e = ast_new(AstNodeKind_typedef_decl); + e->as.typedef_decl = calloc(1, sizeof(TypedefDeclNode)); + e->as.typedef_decl->name = name; + e->ty = ty; + return e; +} + +AstNode* ast_new_struct_def(const char* name) { + AstNode* e = ast_new(AstNodeKind_struct_def); + e->as.struct_def = calloc(1, sizeof(StructDefNode)); + e->as.struct_def->name = name; + return e; +} + +AstNode* ast_new_union_def(const char* name) { + AstNode* e = ast_new(AstNodeKind_union_def); + e->as.union_def = calloc(1, sizeof(UnionDefNode)); + e->as.union_def->name = name; + return e; +} + +AstNode* ast_new_enum_def(const char* name) { + AstNode* e = ast_new(AstNodeKind_enum_def); + e->as.enum_def = calloc(1, sizeof(EnumDefNode)); + e->as.enum_def->name = name; + return e; +} + int type_sizeof_struct(Type* ty) { int next_offset = 0; int struct_align = 0; - for (int i = 0; i < members_of(ty)->node_len; ++i) { - AstNode* member = &members_of(ty)->node_items[i]; + for (int i = 0; i < members_of(ty)->as.list->len; ++i) { + AstNode* member = &members_of(ty)->as.list->items[i]; int size = type_sizeof(member->ty); int align = type_alignof(member->ty); @@ -431,8 +653,8 @@ int type_sizeof_union(Type* ty) { int union_size = 0; int union_align = 0; - for (int i = 0; i < members_of(ty)->node_len; ++i) { - AstNode* member = &members_of(ty)->node_items[i]; + for (int i = 0; i < members_of(ty)->as.list->len; ++i) { + AstNode* member = &members_of(ty)->as.list->items[i]; int size = type_sizeof(member->ty); int align = type_alignof(member->ty); @@ -450,8 +672,8 @@ int type_sizeof_union(Type* ty) { int type_alignof_struct(Type* ty) { int struct_align = 0; - for (int i = 0; i < members_of(ty)->node_len; ++i) { - AstNode* member = &members_of(ty)->node_items[i]; + for (int i = 0; i < members_of(ty)->as.list->len; ++i) { + AstNode* member = &members_of(ty)->as.list->items[i]; int align = type_alignof(member->ty); if (struct_align < align) { @@ -464,8 +686,8 @@ int type_alignof_struct(Type* ty) { int type_alignof_union(Type* ty) { int union_align = 0; - for (int i = 0; i < members_of(ty)->node_len; ++i) { - AstNode* member = &members_of(ty)->node_items[i]; + for (int i = 0; i < members_of(ty)->as.list->len; ++i) { + AstNode* member = &members_of(ty)->as.list->items[i]; int align = type_alignof(member->ty); if (union_align < align) { @@ -485,13 +707,13 @@ int type_offsetof(Type* ty, const char* name) { int next_offset = 0; - for (int i = 0; i < members_of(ty)->node_len; ++i) { - AstNode* member = &members_of(ty)->node_items[i]; + for (int i = 0; i < members_of(ty)->as.list->len; ++i) { + AstNode* member = &members_of(ty)->as.list->items[i]; int size = type_sizeof(member->ty); int align = type_alignof(member->ty); next_offset = to_aligned(next_offset, align); - if (strcmp(member->name, name) == 0) { + if (strcmp(member->as.struct_member->name, name) == 0) { return next_offset; } next_offset += size; @@ -505,9 +727,9 @@ Type* type_member_typeof(Type* ty, const char* name) { fatal_error("type_member_typeof: type is neither a struct nor a union"); } - for (int i = 0; i < members_of(ty)->node_len; ++i) { - AstNode* member = &members_of(ty)->node_items[i]; - if (strcmp(member->name, name) == 0) { + for (int i = 0; i < members_of(ty)->as.list->len; ++i) { + AstNode* member = &members_of(ty)->as.list->items[i]; + if (strcmp(member->as.struct_member->name, name) == 0) { return member->ty; } } @@ -136,38 +136,226 @@ typedef enum { const char* astnode_kind_stringify(AstNodeKind k); -#define node_items __n1 -#define node_len __i1 -#define node_cap __i2 -#define node_expr __n1 -#define node_lhs __n1 -#define node_rhs __n2 -#define node_operand __n1 -#define node_cond __n1 -#define node_init __n2 -#define node_update __n3 -#define node_then __n2 -#define node_else __n3 -#define node_body __n4 -#define node_members __n1 -#define node_params __n1 -#define node_args __n1 -#define node_int_value __i1 -#define node_idx __i1 -#define node_op __i1 -#define node_stack_offset __i1 -#define node_stack_size __i1 +// Expression nodes +typedef struct { + int value; +} IntExprNode; + +typedef struct { + int idx; +} StrExprNode; + +typedef struct { + int op; + AstNode* operand; +} UnaryExprNode; + +typedef struct { + int op; + AstNode* lhs; + AstNode* rhs; +} BinaryExprNode; + +typedef struct { + int op; + AstNode* lhs; + AstNode* rhs; +} LogicalExprNode; + +typedef struct { + int op; + AstNode* lhs; + AstNode* rhs; +} AssignExprNode; + +typedef struct { + AstNode* operand; +} CastExprNode; + +typedef struct { + AstNode* cond; + AstNode* then; + AstNode* else_; +} CondExprNode; + +typedef struct { + AstNode* operand; +} DerefExprNode; + +typedef struct { + AstNode* operand; +} RefExprNode; + +typedef struct { + const char* name; + AstNode* args; +} FuncCallNode; + +// Statement nodes +typedef struct { + AstNode* cond; + AstNode* then; + AstNode* else_; +} IfStmtNode; + +typedef struct { + AstNode* init; + AstNode* cond; + AstNode* update; + AstNode* body; +} ForStmtNode; + +typedef struct { + AstNode* cond; + AstNode* body; +} DoWhileStmtNode; + +typedef struct { + AstNode* expr; + AstNode* body; +} SwitchStmtNode; + +typedef struct { + int value; + AstNode* body; +} CaseLabelNode; + +typedef struct { + AstNode* body; +} DefaultLabelNode; + +typedef struct { + const char* name; + AstNode* body; +} LabelStmtNode; + +typedef struct { + AstNode* expr; +} ReturnStmtNode; + +typedef struct { + const char* label; +} GotoStmtNode; + +typedef struct { + AstNode* expr; +} ExprStmtNode; + +// Declaration nodes +typedef struct { + const char* name; + AstNode* params; + AstNode* body; + int stack_size; +} FuncDefNode; + +typedef struct { + const char* name; + int stack_offset; +} LvarNode; + +typedef struct { + AstNode* expr; +} LvarDeclNode; + +typedef struct { + const char* name; + int stack_offset; +} ParamNode; + +typedef struct { + const char* name; + AstNode* expr; +} GvarDeclNode; + +typedef struct { + const char* name; + AstNode* members; +} StructDefNode; + +typedef struct { + const char* name; + AstNode* members; +} UnionDefNode; + +typedef struct { + const char* name; + AstNode* members; +} EnumDefNode; + +typedef struct { + const char* name; + int value; +} EnumMemberNode; + +typedef struct { + const char* name; + AstNode* init; +} DeclaratorNode; + +typedef struct { + const char* name; +} FuncNode; + +typedef struct { + const char* name; +} GvarNode; + +typedef struct { + const char* name; +} StructMemberNode; + +typedef struct { + const char* name; +} TypedefDeclNode; + +typedef struct { + AstNode* items; + int len; + int cap; +} ListNode; struct AstNode { AstNodeKind kind; - const char* name; Type* ty; - struct AstNode* __n1; - struct AstNode* __n2; - struct AstNode* __n3; - struct AstNode* __n4; - int __i1; - int __i2; + union { + IntExprNode* int_expr; + StrExprNode* str_expr; + UnaryExprNode* unary_expr; + BinaryExprNode* binary_expr; + LogicalExprNode* logical_expr; + AssignExprNode* assign_expr; + CastExprNode* cast_expr; + CondExprNode* cond_expr; + DerefExprNode* deref_expr; + RefExprNode* ref_expr; + FuncCallNode* func_call; + IfStmtNode* if_stmt; + ForStmtNode* for_stmt; + DoWhileStmtNode* do_while_stmt; + SwitchStmtNode* switch_stmt; + CaseLabelNode* case_label; + DefaultLabelNode* default_label; + LabelStmtNode* label_stmt; + ReturnStmtNode* return_stmt; + GotoStmtNode* goto_stmt; + ExprStmtNode* expr_stmt; + FuncDefNode* func_def; + LvarNode* lvar; + LvarDeclNode* lvar_decl; + ParamNode* param; + GvarDeclNode* gvar_decl; + StructDefNode* struct_def; + UnionDefNode* union_def; + EnumDefNode* enum_def; + EnumMemberNode* enum_member; + DeclaratorNode* declarator; + FuncNode* func; + GvarNode* gvar; + StructMemberNode* struct_member; + TypedefDeclNode* typedef_decl; + ListNode* list; + } as; }; typedef struct { @@ -190,5 +378,34 @@ AstNode* ast_new_ref_expr(AstNode* operand); AstNode* ast_new_deref_expr(AstNode* operand); AstNode* ast_new_member_access_expr(AstNode* obj, const char* name); AstNode* ast_new_cast_expr(AstNode* operand, Type* result_ty); +AstNode* ast_new_logical_expr(int op, AstNode* lhs, AstNode* rhs); +AstNode* ast_new_cond_expr(AstNode* cond, AstNode* then, AstNode* else_); +AstNode* ast_new_str_expr(int idx, Type* ty); +AstNode* ast_new_func_call(const char* name, Type* ty); +AstNode* ast_new_func(const char* name, Type* ty); +AstNode* ast_new_gvar(const char* name, Type* ty); +AstNode* ast_new_lvar(const char* name, int stack_offset, Type* ty); + +AstNode* ast_new_nop(void); +AstNode* ast_new_break_stmt(void); +AstNode* ast_new_continue_stmt(void); +AstNode* ast_new_return_stmt(AstNode* expr); +AstNode* ast_new_expr_stmt(AstNode* expr); +AstNode* ast_new_if_stmt(AstNode* cond, AstNode* then, AstNode* else_); +AstNode* ast_new_for_stmt(AstNode* init, AstNode* cond, AstNode* update, AstNode* body); +AstNode* ast_new_do_while_stmt(AstNode* cond, AstNode* body); +AstNode* ast_new_switch_stmt(AstNode* expr); +AstNode* ast_new_case_label(int value, AstNode* body); +AstNode* ast_new_default_label(AstNode* body); +AstNode* ast_new_goto_stmt(const char* label); +AstNode* ast_new_label_stmt(const char* name, AstNode* body); + +AstNode* ast_new_declarator(const char* name, Type* ty); +AstNode* ast_new_func_def(const char* name, Type* ty, AstNode* params, AstNode* body, int stack_size); +AstNode* ast_new_enum_member(const char* name, int value); +AstNode* ast_new_typedef_decl(const char* name, Type* ty); +AstNode* ast_new_struct_def(const char* name); +AstNode* ast_new_union_def(const char* name); +AstNode* ast_new_enum_def(const char* name); #endif diff --git a/src/codegen.c b/src/codegen.c index d35772f..6aac6c6 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -53,49 +53,49 @@ static const char* param_reg(int n) { } } -static void codegen_func_prologue(CodeGen* g, AstNode* ast) { +static void codegen_func_prologue(CodeGen* g, FuncDefNode* func_def) { fprintf(g->out, " push rbp\n"); fprintf(g->out, " mov rbp, rsp\n"); - for (int i = 0, j = 0; i < ast->node_params->node_len; ++i) { - AstNode* param = &ast->node_params->node_items[i]; - if (param->node_stack_offset >= 0) { + for (int i = 0, j = 0; i < func_def->params->as.list->len; ++i) { + AstNode* param = &func_def->params->as.list->items[i]; + if (param->as.param->stack_offset >= 0) { fprintf(g->out, " push %s\n", param_reg(j++)); } } // Note: rsp must be aligned to 8. - fprintf(g->out, " sub rsp, %d\n", to_aligned(ast->node_stack_size, 8)); + fprintf(g->out, " sub rsp, %d\n", to_aligned(func_def->stack_size, 8)); } -static void codegen_func_epilogue(CodeGen* g, AstNode*) { +static void codegen_func_epilogue(CodeGen* g) { fprintf(g->out, " mov rsp, rbp\n"); fprintf(g->out, " pop rbp\n"); fprintf(g->out, " ret\n"); } -static void codegen_int_expr(CodeGen* g, AstNode* ast) { - fprintf(g->out, " mov rax, %d\n", ast->node_int_value); +static void codegen_int_expr(CodeGen* g, IntExprNode* expr) { + fprintf(g->out, " mov rax, %d\n", expr->value); } -static void codegen_str_expr(CodeGen* g, AstNode* ast) { - fprintf(g->out, " lea rax, .Lstr__%d[rip]\n", ast->node_idx); +static void codegen_str_expr(CodeGen* g, StrExprNode* expr) { + fprintf(g->out, " lea rax, .Lstr__%d[rip]\n", expr->idx); } -static void codegen_unary_expr(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_operand, GenMode_rval); - if (ast->node_op == TokenKind_not) { +static void codegen_unary_expr(CodeGen* g, UnaryExprNode* expr) { + codegen_expr(g, expr->operand, GenMode_rval); + if (expr->op == TokenKind_not) { fprintf(g->out, " mov rdi, 0\n"); fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " sete al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_tilde) { + } else if (expr->op == TokenKind_tilde) { fprintf(g->out, " not rax\n"); } else { unreachable(); } } -static void codegen_ref_expr(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_operand, GenMode_lval); +static void codegen_ref_expr(CodeGen* g, RefExprNode* expr) { + codegen_expr(g, expr->operand, GenMode_lval); } static void codegen_lval2rval(CodeGen* g, Type* ty) { @@ -117,22 +117,22 @@ static void codegen_lval2rval(CodeGen* g, Type* ty) { } } -static void codegen_deref_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { - codegen_expr(g, ast->node_operand, GenMode_rval); +static void codegen_deref_expr(CodeGen* g, DerefExprNode* expr, GenMode gen_mode) { + codegen_expr(g, expr->operand, GenMode_rval); if (gen_mode == GenMode_rval) { - codegen_lval2rval(g, ast->node_operand->ty->base); + codegen_lval2rval(g, expr->operand->ty->base); } } -static void codegen_cast_expr(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_operand, GenMode_rval); +static void codegen_cast_expr(CodeGen* g, CastExprNode* expr, Type* ty) { + codegen_expr(g, expr->operand, GenMode_rval); // (void) cast does nothing. - if (ast->ty->kind == TypeKind_void) + if (ty->kind == TypeKind_void) return; - int src_size = type_sizeof(ast->node_operand->ty); - int dst_size = type_sizeof(ast->ty); + int src_size = type_sizeof(expr->operand->ty); + int dst_size = type_sizeof(ty); if (src_size == dst_size) return; @@ -164,76 +164,76 @@ static void codegen_cast_expr(CodeGen* g, AstNode* ast) { } } -static void codegen_logical_expr(CodeGen* g, AstNode* ast) { +static void codegen_logical_expr(CodeGen* g, LogicalExprNode* expr) { int label = codegen_new_label(g); - if (ast->node_op == TokenKind_andand) { - codegen_expr(g, ast->node_lhs, GenMode_rval); + if (expr->op == TokenKind_andand) { + codegen_expr(g, expr->lhs, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); - codegen_expr(g, ast->node_rhs, GenMode_rval); + codegen_expr(g, expr->rhs, GenMode_rval); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); fprintf(g->out, " mov rax, 0\n"); fprintf(g->out, ".Lend%d:\n", label); } else { - codegen_expr(g, ast->node_lhs, GenMode_rval); + codegen_expr(g, expr->lhs, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); fprintf(g->out, " mov rax, 1\n"); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); - codegen_expr(g, ast->node_rhs, GenMode_rval); + codegen_expr(g, expr->rhs, GenMode_rval); fprintf(g->out, ".Lend%d:\n", label); } } -static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { - codegen_expr(g, ast->node_lhs, gen_mode); +static void codegen_binary_expr(CodeGen* g, BinaryExprNode* expr, GenMode gen_mode) { + codegen_expr(g, expr->lhs, gen_mode); fprintf(g->out, " push rax\n"); - codegen_expr(g, ast->node_rhs, gen_mode); + codegen_expr(g, expr->rhs, gen_mode); fprintf(g->out, " mov rdi, rax\n"); fprintf(g->out, " pop rax\n"); // rax=lhs, rdi=rhs - if (ast->node_op == TokenKind_plus) { + if (expr->op == TokenKind_plus) { fprintf(g->out, " add rax, rdi\n"); - } else if (ast->node_op == TokenKind_minus) { + } else if (expr->op == TokenKind_minus) { fprintf(g->out, " sub rax, rdi\n"); - } else if (ast->node_op == TokenKind_star) { + } else if (expr->op == TokenKind_star) { fprintf(g->out, " imul rax, rdi\n"); - } else if (ast->node_op == TokenKind_slash) { + } else if (expr->op == TokenKind_slash) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); - } else if (ast->node_op == TokenKind_percent) { + } else if (expr->op == TokenKind_percent) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); fprintf(g->out, " mov rax, rdx\n"); - } else if (ast->node_op == TokenKind_and) { + } else if (expr->op == TokenKind_and) { fprintf(g->out, " and rax, rdi\n"); - } else if (ast->node_op == TokenKind_or) { + } else if (expr->op == TokenKind_or) { fprintf(g->out, " or rax, rdi\n"); - } else if (ast->node_op == TokenKind_xor) { + } else if (expr->op == TokenKind_xor) { fprintf(g->out, " xor rax, rdi\n"); - } else if (ast->node_op == TokenKind_lshift) { + } else if (expr->op == TokenKind_lshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " shl rax, cl\n"); - } else if (ast->node_op == TokenKind_rshift) { + } else if (expr->op == TokenKind_rshift) { // TODO: check if the operand is signed or unsigned fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " sar rax, cl\n"); - } else if (ast->node_op == TokenKind_eq) { + } else if (expr->op == TokenKind_eq) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " sete al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_ne) { + } else if (expr->op == TokenKind_ne) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " setne al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_lt) { + } else if (expr->op == TokenKind_lt) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " setl al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_le) { + } else if (expr->op == TokenKind_le) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " setle al\n"); fprintf(g->out, " movzb rax, al\n"); @@ -242,51 +242,51 @@ static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { } } -static void codegen_cond_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { +static void codegen_cond_expr(CodeGen* g, CondExprNode* expr, GenMode gen_mode) { int label = codegen_new_label(g); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, expr->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); - codegen_expr(g, ast->node_then, gen_mode); + codegen_expr(g, expr->then, gen_mode); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); - codegen_expr(g, ast->node_else, gen_mode); + codegen_expr(g, expr->else_, gen_mode); fprintf(g->out, ".Lend%d:\n", label); } -static void codegen_assign_expr_helper(CodeGen* g, AstNode* ast) { - if (ast->node_op == TokenKind_assign) { +static void codegen_assign_expr_helper(CodeGen* g, AssignExprNode* expr) { + if (expr->op == TokenKind_assign) { return; } fprintf(g->out, " mov rdi, rax\n"); fprintf(g->out, " mov rax, [rsp]\n"); - codegen_lval2rval(g, ast->node_lhs->ty); + codegen_lval2rval(g, expr->lhs->ty); - if (ast->node_op == TokenKind_assign_add) { + if (expr->op == TokenKind_assign_add) { fprintf(g->out, " add rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_sub) { + } else if (expr->op == TokenKind_assign_sub) { fprintf(g->out, " sub rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_mul) { + } else if (expr->op == TokenKind_assign_mul) { fprintf(g->out, " imul rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_div) { + } else if (expr->op == TokenKind_assign_div) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); - } else if (ast->node_op == TokenKind_assign_mod) { + } else if (expr->op == TokenKind_assign_mod) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); fprintf(g->out, " mov rax, rdx\n"); - } else if (ast->node_op == TokenKind_assign_or) { + } else if (expr->op == TokenKind_assign_or) { fprintf(g->out, " or rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_and) { + } else if (expr->op == TokenKind_assign_and) { fprintf(g->out, " and rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_xor) { + } else if (expr->op == TokenKind_assign_xor) { fprintf(g->out, " xor rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_lshift) { + } else if (expr->op == TokenKind_assign_lshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " shl rax, cl\n"); - } else if (ast->node_op == TokenKind_assign_rshift) { + } else if (expr->op == TokenKind_assign_rshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " sar rax, cl\n"); } else { @@ -294,13 +294,13 @@ static void codegen_assign_expr_helper(CodeGen* g, AstNode* ast) { } } -static void codegen_assign_expr(CodeGen* g, AstNode* ast) { - int sizeof_lhs = type_sizeof(ast->node_lhs->ty); +static void codegen_assign_expr(CodeGen* g, AssignExprNode* expr) { + int sizeof_lhs = type_sizeof(expr->lhs->ty); - codegen_expr(g, ast->node_lhs, GenMode_lval); + codegen_expr(g, expr->lhs, GenMode_lval); fprintf(g->out, " push rax\n"); - codegen_expr(g, ast->node_rhs, GenMode_rval); - codegen_assign_expr_helper(g, ast); + codegen_expr(g, expr->rhs, GenMode_rval); + codegen_assign_expr_helper(g, expr); fprintf(g->out, " pop rdi\n"); if (sizeof_lhs == 1) { fprintf(g->out, " mov BYTE PTR [rdi], al\n"); @@ -311,7 +311,7 @@ static void codegen_assign_expr(CodeGen* g, AstNode* ast) { } else if (sizeof_lhs == 8) { fprintf(g->out, " mov [rdi], rax\n"); } else { - if (ast->node_op != TokenKind_assign) { + if (expr->op != TokenKind_assign) { unimplemented(); } // rax: address of rhs @@ -325,11 +325,11 @@ static void codegen_assign_expr(CodeGen* g, AstNode* ast) { } static void codegen_args(CodeGen* g, AstNode* args) { - int* required_gp_regs_for_each_arg = calloc(args->node_len, sizeof(int)); + int* required_gp_regs_for_each_arg = calloc(args->as.list->len, sizeof(int)); int gp_regs = 6; - for (int i = 0; i < args->node_len; ++i) { - AstNode* arg = &args->node_items[i]; + for (int i = 0; i < args->as.list->len; ++i) { + AstNode* arg = &args->as.list->items[i]; int ty_size = type_sizeof(arg->ty); // TODO if (arg->ty->kind == TypeKind_array) { @@ -353,8 +353,8 @@ static void codegen_args(CodeGen* g, AstNode* args) { // Evaluate arguments in the reverse order (right to left). // Arguments passed by stack. - for (int i = args->node_len - 1; i >= 0; --i) { - AstNode* arg = &args->node_items[i]; + for (int i = args->as.list->len - 1; i >= 0; --i) { + AstNode* arg = &args->as.list->items[i]; if (required_gp_regs_for_each_arg[i] == 0) { codegen_expr(g, arg, GenMode_rval); int ty_size = type_sizeof(arg->ty); @@ -373,8 +373,8 @@ static void codegen_args(CodeGen* g, AstNode* args) { } } // Arguments passed by registers. - for (int i = args->node_len - 1; i >= 0; --i) { - AstNode* arg = &args->node_items[i]; + for (int i = args->as.list->len - 1; i >= 0; --i) { + AstNode* arg = &args->as.list->items[i]; if (required_gp_regs_for_each_arg[i] != 0) { codegen_expr(g, arg, GenMode_rval); if (required_gp_regs_for_each_arg[i] == 1) { @@ -387,19 +387,19 @@ static void codegen_args(CodeGen* g, AstNode* args) { } } // Pop pushed arguments onto registers. - for (int i = 0, j = 0; i < args->node_len; ++i) { + for (int i = 0, j = 0; i < args->as.list->len; ++i) { for (int k = 0; k < required_gp_regs_for_each_arg[i]; ++k) { fprintf(g->out, " pop %s\n", param_reg(j++)); } } } -static void codegen_func_call(CodeGen* g, AstNode* ast) { - const char* func_name = ast->name; +static void codegen_func_call(CodeGen* g, FuncCallNode* call) { + const char* func_name = call->name; if (strcmp(func_name, "__ducc_va_start") == 0) { fprintf(g->out, " # __ducc_va_start BEGIN\n"); - AstNode* va_list_args = &ast->node_args->node_items[0]; + AstNode* va_list_args = &call->args->as.list->items[0]; codegen_expr(g, va_list_args, GenMode_rval); fprintf(g->out, " mov rdi, rax\n"); @@ -429,12 +429,12 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { fprintf(g->out, " # __ducc_va_arg BEGIN\n"); // Evaluate va_list argument (first argument) - AstNode* va_list_arg = &ast->node_args->node_items[0]; + AstNode* va_list_arg = &call->args->as.list->items[0]; codegen_expr(g, va_list_arg, GenMode_rval); fprintf(g->out, " mov rdi, rax\n"); // rdi = pointer to va_list // Evaluate size argument (second argument) - AstNode* size_arg = &ast->node_args->node_items[1]; + AstNode* size_arg = &call->args->as.list->items[1]; codegen_expr(g, size_arg, GenMode_rval); fprintf(g->out, " mov rsi, rax\n"); // rsi = size @@ -466,12 +466,12 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { return; } - AstNode* args = ast->node_args; + AstNode* args = call->args; int gp_regs = 6; int pass_by_stack_offset = -16; - for (int i = 0; i < args->node_len; ++i) { - AstNode* arg = &args->node_items[i]; + for (int i = 0; i < args->as.list->len; ++i) { + AstNode* arg = &args->as.list->items[i]; int ty_size = type_sizeof(arg->ty); // TODO if (arg->ty->kind == TypeKind_array) { @@ -523,61 +523,61 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { fprintf(g->out, " add rsp, %d\n", -pass_by_stack_offset - 16); } -static void codegen_lvar(CodeGen* g, AstNode* ast, GenMode gen_mode) { - fprintf(g->out, " lea rax, %d[rbp]\n", -ast->node_stack_offset); +static void codegen_lvar(CodeGen* g, LvarNode* lvar, Type* ty, GenMode gen_mode) { + fprintf(g->out, " lea rax, %d[rbp]\n", -lvar->stack_offset); if (gen_mode == GenMode_rval) { - codegen_lval2rval(g, ast->ty); + codegen_lval2rval(g, ty); } } -static void codegen_gvar(CodeGen* g, AstNode* ast, GenMode gen_mode) { - fprintf(g->out, " lea rax, %s[rip]\n", ast->name); +static void codegen_gvar(CodeGen* g, GvarNode* gvar, Type* ty, GenMode gen_mode) { + fprintf(g->out, " lea rax, %s[rip]\n", gvar->name); if (gen_mode == GenMode_rval) { - codegen_lval2rval(g, ast->ty); + codegen_lval2rval(g, ty); } } -static void codegen_func_ref(CodeGen* g, AstNode* ast) { - fprintf(g->out, " lea rax, %s[rip]\n", ast->name); +static void codegen_func_ref(CodeGen* g, FuncNode* func) { + fprintf(g->out, " lea rax, %s[rip]\n", func->name); } static void codegen_composite_expr(CodeGen* g, AstNode* ast) { // Standard C does not have composite expression, but ducc internally has. - for (int i = 0; i < ast->node_len; ++i) { - AstNode* expr = ast->node_items + i; + for (int i = 0; i < ast->as.list->len; ++i) { + AstNode* expr = ast->as.list->items + i; codegen_expr(g, expr, GenMode_rval); } } static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { if (ast->kind == AstNodeKind_int_expr) { - codegen_int_expr(g, ast); + codegen_int_expr(g, ast->as.int_expr); } else if (ast->kind == AstNodeKind_str_expr) { - codegen_str_expr(g, ast); + codegen_str_expr(g, ast->as.str_expr); } else if (ast->kind == AstNodeKind_unary_expr) { - codegen_unary_expr(g, ast); + codegen_unary_expr(g, ast->as.unary_expr); } else if (ast->kind == AstNodeKind_ref_expr) { - codegen_ref_expr(g, ast); + codegen_ref_expr(g, ast->as.ref_expr); } else if (ast->kind == AstNodeKind_deref_expr) { - codegen_deref_expr(g, ast, gen_mode); + codegen_deref_expr(g, ast->as.deref_expr, gen_mode); } else if (ast->kind == AstNodeKind_cast_expr) { - codegen_cast_expr(g, ast); + codegen_cast_expr(g, ast->as.cast_expr, ast->ty); } else if (ast->kind == AstNodeKind_binary_expr) { - codegen_binary_expr(g, ast, gen_mode); + codegen_binary_expr(g, ast->as.binary_expr, gen_mode); } else if (ast->kind == AstNodeKind_cond_expr) { - codegen_cond_expr(g, ast, gen_mode); + codegen_cond_expr(g, ast->as.cond_expr, gen_mode); } else if (ast->kind == AstNodeKind_logical_expr) { - codegen_logical_expr(g, ast); + codegen_logical_expr(g, ast->as.logical_expr); } else if (ast->kind == AstNodeKind_assign_expr) { - codegen_assign_expr(g, ast); + codegen_assign_expr(g, ast->as.assign_expr); } else if (ast->kind == AstNodeKind_func_call) { - codegen_func_call(g, ast); + codegen_func_call(g, ast->as.func_call); } else if (ast->kind == AstNodeKind_lvar) { - codegen_lvar(g, ast, gen_mode); + codegen_lvar(g, ast->as.lvar, ast->ty, gen_mode); } else if (ast->kind == AstNodeKind_gvar) { - codegen_gvar(g, ast, gen_mode); + codegen_gvar(g, ast->as.gvar, ast->ty, gen_mode); } else if (ast->kind == AstNodeKind_func) { - codegen_func_ref(g, ast); + codegen_func_ref(g, ast->as.func); } else if (ast->kind == AstNodeKind_list) { codegen_composite_expr(g, ast); } else { @@ -585,44 +585,44 @@ static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { } } -static void codegen_return_stmt(CodeGen* g, AstNode* ast) { - if (ast->node_expr) { - codegen_expr(g, ast->node_expr, GenMode_rval); +static void codegen_return_stmt(CodeGen* g, ReturnStmtNode* stmt) { + if (stmt->expr) { + codegen_expr(g, stmt->expr, GenMode_rval); } - codegen_func_epilogue(g, ast); + codegen_func_epilogue(g); } -static void codegen_if_stmt(CodeGen* g, AstNode* ast) { +static void codegen_if_stmt(CodeGen* g, IfStmtNode* stmt) { int label = codegen_new_label(g); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); - codegen_stmt(g, ast->node_then); + codegen_stmt(g, stmt->then); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); - if (ast->node_else) { - codegen_stmt(g, ast->node_else); + if (stmt->else_) { + codegen_stmt(g, stmt->else_); } fprintf(g->out, ".Lend%d:\n", label); } -static void codegen_for_stmt(CodeGen* g, AstNode* ast) { +static void codegen_for_stmt(CodeGen* g, ForStmtNode* stmt) { int label = codegen_new_label(g); ++g->loop_labels; *g->loop_labels = label; - if (ast->node_init) { - codegen_expr(g, ast->node_init, GenMode_rval); + if (stmt->init) { + codegen_expr(g, stmt->init, GenMode_rval); } fprintf(g->out, ".Lbegin%d:\n", label); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lend%d\n", label); - codegen_stmt(g, ast->node_body); + codegen_stmt(g, stmt->body); fprintf(g->out, ".Lcontinue%d:\n", label); - if (ast->node_update) { - codegen_expr(g, ast->node_update, GenMode_rval); + if (stmt->update) { + codegen_expr(g, stmt->update, GenMode_rval); } fprintf(g->out, " jmp .Lbegin%d\n", label); fprintf(g->out, ".Lend%d:\n", label); @@ -630,15 +630,15 @@ static void codegen_for_stmt(CodeGen* g, AstNode* ast) { --g->loop_labels; } -static void codegen_do_while_stmt(CodeGen* g, AstNode* ast) { +static void codegen_do_while_stmt(CodeGen* g, DoWhileStmtNode* stmt) { int label = codegen_new_label(g); ++g->loop_labels; *g->loop_labels = label; fprintf(g->out, ".Lbegin%d:\n", label); - codegen_stmt(g, ast->node_body); + codegen_stmt(g, stmt->body); fprintf(g->out, ".Lcontinue%d:\n", label); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lend%d\n", label); fprintf(g->out, " jmp .Lbegin%d\n", label); @@ -647,7 +647,7 @@ static void codegen_do_while_stmt(CodeGen* g, AstNode* ast) { --g->loop_labels; } -static void codegen_break_stmt(CodeGen* g, AstNode*) { +static void codegen_break_stmt(CodeGen* g) { if (g->switch_label != -1) { fprintf(g->out, " jmp .Lend%d\n", g->switch_label); } else { @@ -656,18 +656,18 @@ static void codegen_break_stmt(CodeGen* g, AstNode*) { } } -static void codegen_continue_stmt(CodeGen* g, AstNode*) { +static void codegen_continue_stmt(CodeGen* g) { int label = *g->loop_labels; fprintf(g->out, " jmp .Lcontinue%d\n", label); } -static void codegen_goto_stmt(CodeGen* g, AstNode* ast) { - fprintf(g->out, " jmp .L%s__%s\n", g->current_func->name, ast->name); +static void codegen_goto_stmt(CodeGen* g, GotoStmtNode* stmt) { + fprintf(g->out, " jmp .L%s__%s\n", g->current_func->as.func_def->name, stmt->label); } -static void codegen_label_stmt(CodeGen* g, AstNode* ast) { - fprintf(g->out, ".L%s__%s:\n", g->current_func->name, ast->name); - codegen_stmt(g, ast->node_body); +static void codegen_label_stmt(CodeGen* g, LabelStmtNode* stmt) { + fprintf(g->out, ".L%s__%s:\n", g->current_func->as.func_def->name, stmt->name); + codegen_stmt(g, stmt->body); } // Helper to collect case values from the switch body @@ -676,15 +676,15 @@ static void collect_cases(AstNode* stmt, int* case_values, int* case_labels, int return; if (stmt->kind == AstNodeKind_case_label) { - case_values[*n_cases] = stmt->node_int_value; + case_values[*n_cases] = stmt->as.case_label->value; case_labels[*n_cases] = *n_cases + 1; (*n_cases)++; - collect_cases(stmt->node_body, case_values, case_labels, n_cases); + collect_cases(stmt->as.case_label->body, case_values, case_labels, n_cases); } else if (stmt->kind == AstNodeKind_default_label) { - collect_cases(stmt->node_body, case_values, case_labels, n_cases); + collect_cases(stmt->as.default_label->body, case_values, case_labels, n_cases); } else if (stmt->kind == AstNodeKind_list) { - for (int i = 0; i < stmt->node_len; i++) { - collect_cases(stmt->node_items + i, case_values, case_labels, n_cases); + for (int i = 0; i < stmt->as.list->len; i++) { + collect_cases(stmt->as.list->items + i, case_values, case_labels, n_cases); } } } @@ -694,23 +694,24 @@ static bool codegen_switch_body(CodeGen* g, AstNode* stmt, int* case_values, int return false; if (stmt->kind == AstNodeKind_case_label) { - int value = stmt->node_int_value; + int value = stmt->as.case_label->value; for (int i = 0; i < n_cases; i++) { if (case_values[i] == value) { fprintf(g->out, ".Lcase%d_%d:\n", g->switch_label, case_labels[i]); break; } } - codegen_stmt(g, stmt->node_body); + codegen_stmt(g, stmt->as.case_label->body); return false; } else if (stmt->kind == AstNodeKind_default_label) { fprintf(g->out, ".Ldefault%d:\n", g->switch_label); - codegen_stmt(g, stmt->node_body); + codegen_stmt(g, stmt->as.default_label->body); return true; } else if (stmt->kind == AstNodeKind_list) { bool default_label_emitted = false; - for (int i = 0; i < stmt->node_len; i++) { - default_label_emitted |= codegen_switch_body(g, stmt->node_items + i, case_values, case_labels, n_cases); + for (int i = 0; i < stmt->as.list->len; i++) { + default_label_emitted |= + codegen_switch_body(g, stmt->as.list->items + i, case_values, case_labels, n_cases); } return default_label_emitted; } else { @@ -719,7 +720,7 @@ static bool codegen_switch_body(CodeGen* g, AstNode* stmt, int* case_values, int } } -static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { +static void codegen_switch_stmt(CodeGen* g, SwitchStmtNode* stmt) { int switch_label = codegen_new_label(g); int prev_switch_label = g->switch_label; g->switch_label = switch_label; @@ -728,10 +729,10 @@ static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { int case_values[256]; int case_labels[256]; int n_cases = 0; - collect_cases(ast->node_body, case_values, case_labels, &n_cases); + collect_cases(stmt->body, case_values, case_labels, &n_cases); // Generate jump instructions. - codegen_expr(g, ast->node_expr, GenMode_rval); + codegen_expr(g, stmt->expr, GenMode_rval); for (int i = 0; i < n_cases; i++) { fprintf(g->out, " cmp rax, %d\n", case_values[i]); fprintf(g->out, " je .Lcase%d_%d\n", switch_label, case_labels[i]); @@ -739,7 +740,7 @@ static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { fprintf(g->out, " jmp .Ldefault%d\n", switch_label); // Generate the switch body with labels. - bool default_label_emitted = codegen_switch_body(g, ast->node_body, case_values, case_labels, n_cases); + bool default_label_emitted = codegen_switch_body(g, stmt->body, case_values, case_labels, n_cases); if (!default_label_emitted) { fprintf(g->out, ".Ldefault%d:\n", switch_label); @@ -749,13 +750,13 @@ static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { g->switch_label = prev_switch_label; } -static void codegen_expr_stmt(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_expr, GenMode_rval); +static void codegen_expr_stmt(CodeGen* g, ExprStmtNode* stmt) { + codegen_expr(g, stmt->expr, GenMode_rval); } static void codegen_block_stmt(CodeGen* g, AstNode* ast) { - for (int i = 0; i < ast->node_len; ++i) { - AstNode* stmt = ast->node_items + i; + for (int i = 0; i < ast->as.list->len; ++i) { + AstNode* stmt = ast->as.list->items + i; codegen_stmt(g, stmt); } } @@ -764,25 +765,25 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) { if (ast->kind == AstNodeKind_list) { codegen_block_stmt(g, ast); } else if (ast->kind == AstNodeKind_return_stmt) { - codegen_return_stmt(g, ast); + codegen_return_stmt(g, ast->as.return_stmt); } else if (ast->kind == AstNodeKind_if_stmt) { - codegen_if_stmt(g, ast); + codegen_if_stmt(g, ast->as.if_stmt); } else if (ast->kind == AstNodeKind_switch_stmt) { - codegen_switch_stmt(g, ast); + codegen_switch_stmt(g, ast->as.switch_stmt); } else if (ast->kind == AstNodeKind_for_stmt) { - codegen_for_stmt(g, ast); + codegen_for_stmt(g, ast->as.for_stmt); } else if (ast->kind == AstNodeKind_do_while_stmt) { - codegen_do_while_stmt(g, ast); + codegen_do_while_stmt(g, ast->as.do_while_stmt); } else if (ast->kind == AstNodeKind_break_stmt) { - codegen_break_stmt(g, ast); + codegen_break_stmt(g); } else if (ast->kind == AstNodeKind_continue_stmt) { - codegen_continue_stmt(g, ast); + codegen_continue_stmt(g); } else if (ast->kind == AstNodeKind_goto_stmt) { - codegen_goto_stmt(g, ast); + codegen_goto_stmt(g, ast->as.goto_stmt); } else if (ast->kind == AstNodeKind_label_stmt) { - codegen_label_stmt(g, ast); + codegen_label_stmt(g, ast->as.label_stmt); } else if (ast->kind == AstNodeKind_expr_stmt) { - codegen_expr_stmt(g, ast); + codegen_expr_stmt(g, ast->as.expr_stmt); } else if (ast->kind == AstNodeKind_lvar_decl) { // Do nothing. } else if (ast->kind == AstNodeKind_nop) { @@ -799,17 +800,17 @@ static void codegen_func(CodeGen* g, AstNode* ast) { g->current_func = ast; if (ast->ty->storage_class != StorageClass_static) { - fprintf(g->out, ".globl %s\n", ast->name); + fprintf(g->out, ".globl %s\n", ast->as.func_def->name); } - fprintf(g->out, "%s:\n", ast->name); + fprintf(g->out, "%s:\n", ast->as.func_def->name); - codegen_func_prologue(g, ast); - codegen_stmt(g, ast->node_body); - if (strcmp(ast->name, "main") == 0) { + codegen_func_prologue(g, ast->as.func_def); + codegen_stmt(g, ast->as.func_def->body); + if (strcmp(ast->as.func_def->name, "main") == 0) { // C99: 5.1.2.2.3 fprintf(g->out, " mov rax, 0\n"); } - codegen_func_epilogue(g, ast); + codegen_func_epilogue(g); fprintf(g->out, "\n"); g->current_func = NULL; @@ -831,48 +832,53 @@ void codegen(Program* prog, FILE* out) { } fprintf(g->out, ".data\n\n"); - for (int i = 0; i < prog->vars->node_len; ++i) { - AstNode* var = prog->vars->node_items + i; - if (var->node_expr) { + for (int i = 0; i < prog->vars->as.list->len; ++i) { + AstNode* var = prog->vars->as.list->items + i; + if (var->as.gvar_decl->expr) { if (type_sizeof(var->ty) == 1) { - if (var->node_expr->kind != AstNodeKind_int_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr) unimplemented(); - fprintf(g->out, " %s: .byte %d\n", var->name, var->node_expr->node_int_value); + fprintf(g->out, " %s: .byte %d\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.int_expr->value); } else if (type_sizeof(var->ty) == 2) { - if (var->node_expr->kind != AstNodeKind_int_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr) unimplemented(); - fprintf(g->out, " %s: .word %d\n", var->name, var->node_expr->node_int_value); + fprintf(g->out, " %s: .word %d\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.int_expr->value); } else if (type_sizeof(var->ty) == 4) { - if (var->node_expr->kind != AstNodeKind_int_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr) unimplemented(); - fprintf(g->out, " %s: .int %d\n", var->name, var->node_expr->node_int_value); + fprintf(g->out, " %s: .int %d\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.int_expr->value); } else if (var->ty->kind == TypeKind_ptr) { - if (var->node_expr->kind == AstNodeKind_ref_expr) { - if (var->node_expr->node_operand->kind != AstNodeKind_gvar) { + if (var->as.gvar_decl->expr->kind == AstNodeKind_ref_expr) { + if (var->as.gvar_decl->expr->as.ref_expr->operand->kind != AstNodeKind_gvar) { unimplemented(); } - fprintf(g->out, " %s: .quad %s\n", var->name, var->node_expr->node_operand->name); - } else if (var->node_expr->kind == AstNodeKind_gvar) { - fprintf(g->out, " %s: .quad %s\n", var->name, var->node_expr->name); + fprintf(g->out, " %s: .quad %s\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.ref_expr->operand->as.gvar->name); + } else if (var->as.gvar_decl->expr->kind == AstNodeKind_gvar) { + fprintf(g->out, " %s: .quad %s\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.gvar->name); } else { unimplemented(); } } else if (var->ty->kind == TypeKind_array && var->ty->base->kind == TypeKind_char) { - if (var->node_expr->kind != AstNodeKind_str_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_str_expr) unimplemented(); - const char* str = prog->str_literals[var->node_expr->node_idx - 1]; - fprintf(g->out, " %s: .string \"%s\"\n", var->name, str); + const char* str = prog->str_literals[var->as.gvar_decl->expr->as.str_expr->idx - 1]; + fprintf(g->out, " %s: .string \"%s\"\n", var->as.gvar_decl->name, str); } else { unimplemented(); } } else { - fprintf(g->out, " %s: .zero %d\n", var->name, type_sizeof(var->ty)); + fprintf(g->out, " %s: .zero %d\n", var->as.gvar_decl->name, type_sizeof(var->ty)); } } fprintf(g->out, ".text\n\n"); - for (int i = 0; i < prog->funcs->node_len; ++i) { - AstNode* func = &prog->funcs->node_items[i]; + for (int i = 0; i < prog->funcs->as.list->len; ++i) { + AstNode* func = &prog->funcs->as.list->items[i]; codegen_func(g, func); } } diff --git a/src/codegen_wasm.c b/src/codegen_wasm.c index e0be383..cb48f38 100644 --- a/src/codegen_wasm.c +++ b/src/codegen_wasm.c @@ -29,77 +29,77 @@ static CodeGen* codegen_new(FILE* out) { static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode); static void codegen_stmt(CodeGen* g, AstNode* ast); -static void codegen_func_prologue(CodeGen* g, AstNode* ast) { - for (int i = 0; i < ast->node_params->node_len; ++i) { - fprintf(g->out, " (param $l_%s i32)", ast->node_params->node_items[i].name); +static void codegen_func_prologue(CodeGen* g, FuncDefNode* func_def) { + for (int i = 0; i < func_def->params->as.list->len; ++i) { + fprintf(g->out, " (param $l_%s i32)", func_def->params->as.list->items[i].as.param->name); } fprintf(g->out, " (result i32)\n"); } -static void codegen_func_epilogue(CodeGen*, AstNode*) { +static void codegen_func_epilogue(CodeGen*) { } -static void codegen_int_expr(CodeGen* g, AstNode* ast) { - fprintf(g->out, " i32.const %d\n", ast->node_int_value); +static void codegen_int_expr(CodeGen* g, IntExprNode* expr) { + fprintf(g->out, " i32.const %d\n", expr->value); } -static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { - codegen_expr(g, ast->node_lhs, gen_mode); - codegen_expr(g, ast->node_rhs, gen_mode); - if (ast->node_op == TokenKind_plus) { +static void codegen_binary_expr(CodeGen* g, BinaryExprNode* expr, GenMode gen_mode) { + codegen_expr(g, expr->lhs, gen_mode); + codegen_expr(g, expr->rhs, gen_mode); + if (expr->op == TokenKind_plus) { fprintf(g->out, " i32.add\n"); - } else if (ast->node_op == TokenKind_minus) { + } else if (expr->op == TokenKind_minus) { fprintf(g->out, " i32.sub\n"); - } else if (ast->node_op == TokenKind_le) { + } else if (expr->op == TokenKind_le) { fprintf(g->out, " i32.le_s\n"); } else { unreachable(); } } -static void codegen_lvar(CodeGen* g, AstNode* ast, GenMode) { - fprintf(g->out, " local.get $l_%s\n", ast->name); +static void codegen_lvar(CodeGen* g, LvarNode* lvar, GenMode) { + fprintf(g->out, " local.get $l_%s\n", lvar->name); } -static void codegen_func_call(CodeGen* g, AstNode* ast) { - AstNode* args = ast->node_args; - for (int i = 0; i < args->node_len; ++i) { - AstNode* arg = args->node_items + i; +static void codegen_func_call(CodeGen* g, FuncCallNode* call) { + AstNode* args = call->args; + for (int i = 0; i < args->as.list->len; ++i) { + AstNode* arg = args->as.list->items + i; codegen_expr(g, arg, GenMode_rval); } - fprintf(g->out, " call $%s\n", ast->name); + fprintf(g->out, " call $%s\n", call->name); } static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { if (ast->kind == AstNodeKind_int_expr) { - codegen_int_expr(g, ast); + codegen_int_expr(g, ast->as.int_expr); } else if (ast->kind == AstNodeKind_binary_expr) { - codegen_binary_expr(g, ast, gen_mode); + codegen_binary_expr(g, ast->as.binary_expr, gen_mode); } else if (ast->kind == AstNodeKind_lvar) { - codegen_lvar(g, ast, gen_mode); + codegen_lvar(g, ast->as.lvar, gen_mode); } else if (ast->kind == AstNodeKind_func_call) { - codegen_func_call(g, ast); + codegen_func_call(g, ast->as.func_call); } else { unreachable(); } } -static void codegen_return_stmt(CodeGen* g, AstNode* ast) { - if (ast->node_expr) { - codegen_expr(g, ast->node_expr, GenMode_rval); +static void codegen_return_stmt(CodeGen* g, ReturnStmtNode* stmt) { + if (stmt->expr) { + codegen_expr(g, stmt->expr, GenMode_rval); } fprintf(g->out, " return\n"); } -static void codegen_if_stmt(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_cond, GenMode_rval); +static void codegen_if_stmt(CodeGen* g, IfStmtNode* stmt) { + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " (if (result i32)\n"); fprintf(g->out, " (then\n"); - codegen_stmt(g, ast->node_then); + codegen_stmt(g, stmt->then); fprintf(g->out, " )\n"); - if (ast->node_else) { + if (stmt->else_) { fprintf(g->out, " (else\n"); - codegen_stmt(g, ast->node_else); + codegen_stmt(g, stmt->else_); fprintf(g->out, " )\n"); } else { fprintf(g->out, " (else\n"); @@ -110,8 +110,8 @@ static void codegen_if_stmt(CodeGen* g, AstNode* ast) { } static void codegen_block_stmt(CodeGen* g, AstNode* ast) { - for (int i = 0; i < ast->node_len; ++i) { - AstNode* stmt = ast->node_items + i; + for (int i = 0; i < ast->as.list->len; ++i) { + AstNode* stmt = ast->as.list->items + i; codegen_stmt(g, stmt); } } @@ -120,9 +120,9 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) { if (ast->kind == AstNodeKind_list) { codegen_block_stmt(g, ast); } else if (ast->kind == AstNodeKind_return_stmt) { - codegen_return_stmt(g, ast); + codegen_return_stmt(g, ast->as.return_stmt); } else if (ast->kind == AstNodeKind_if_stmt) { - codegen_if_stmt(g, ast); + codegen_if_stmt(g, ast->as.if_stmt); } else if (ast->kind == AstNodeKind_nop) { // Do nothing. } else { @@ -133,11 +133,11 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) { static void codegen_func(CodeGen* g, AstNode* ast) { g->current_func = ast; - fprintf(g->out, "(func $%s (export \"%s\")", ast->name, ast->name); + fprintf(g->out, "(func $%s (export \"%s\")", ast->as.func_def->name, ast->as.func_def->name); - codegen_func_prologue(g, ast); - codegen_stmt(g, ast->node_body); - codegen_func_epilogue(g, ast); + codegen_func_prologue(g, ast->as.func_def); + codegen_stmt(g, ast->as.func_def->body); + codegen_func_epilogue(g); fprintf(g->out, ")\n"); g->current_func = NULL; @@ -148,8 +148,8 @@ void codegen_wasm(Program* prog, FILE* out) { fprintf(g->out, "(module\n"); - for (int i = 0; i < prog->funcs->node_len; ++i) { - AstNode* func = prog->funcs->node_items + i; + for (int i = 0; i < prog->funcs->as.list->len; ++i) { + AstNode* func = prog->funcs->as.list->items + i; codegen_func(g, func); } diff --git a/src/parse.c b/src/parse.c index 2818082..59ca219 100644 --- a/src/parse.c +++ b/src/parse.c @@ -257,11 +257,7 @@ static int add_lvar(Parser* p, const char* name, Type* ty, int stack_offset) { static AstNode* generate_temporary_lvar(Parser* p, Type* ty) { int stack_offset = add_lvar(p, NULL, ty, calc_lvar_stack_offset(p, ty)); - AstNode* lvar = ast_new(AstNodeKind_lvar); - lvar->name = NULL; - lvar->node_stack_offset = stack_offset; - lvar->ty = ty; - return lvar; + return ast_new_lvar(NULL, stack_offset, ty); } static int find_gvar(Parser* p, const char* name) { @@ -283,8 +279,8 @@ static int find_func(Parser* p, const char* name) { } static int find_struct(Parser* p, const char* name) { - for (int i = 0; i < p->structs->node_len; ++i) { - if (strcmp(p->structs->node_items[i].name, name) == 0) { + for (int i = 0; i < p->structs->as.list->len; ++i) { + if (strcmp(p->structs->as.list->items[i].as.struct_def->name, name) == 0) { return i; } } @@ -292,8 +288,8 @@ static int find_struct(Parser* p, const char* name) { } static int find_union(Parser* p, const char* name) { - for (int i = 0; i < p->unions->node_len; ++i) { - if (strcmp(p->unions->node_items[i].name, name) == 0) { + for (int i = 0; i < p->unions->as.list->len; ++i) { + if (strcmp(p->unions->as.list->items[i].as.union_def->name, name) == 0) { return i; } } @@ -301,8 +297,8 @@ static int find_union(Parser* p, const char* name) { } static int find_enum(Parser* p, const char* name) { - for (int i = 0; i < p->enums->node_len; ++i) { - if (strcmp(p->enums->node_items[i].name, name) == 0) { + for (int i = 0; i < p->enums->as.list->len; ++i) { + if (strcmp(p->enums->as.list->items[i].as.enum_def->name, name) == 0) { return i; } } @@ -310,9 +306,12 @@ static int find_enum(Parser* p, const char* name) { } static int find_enum_member(Parser* p, const char* name) { - for (int i = 0; i < p->enums->node_len; ++i) { - for (int j = 0; j < p->enums->node_items[i].node_members->node_len; ++j) { - if (strcmp(p->enums->node_items[i].node_members->node_items[j].name, name) == 0) { + for (int i = 0; i < p->enums->as.list->len; ++i) { + AstNode* members = p->enums->as.list->items[i].as.enum_def->members; + if (!members) + continue; + for (int j = 0; j < members->as.list->len; ++j) { + if (strcmp(members->as.list->items[j].as.enum_member->name, name) == 0) { return i * 1000 + j; } } @@ -321,8 +320,8 @@ static int find_enum_member(Parser* p, const char* name) { } static int find_typedef(Parser* p, const char* name) { - for (int i = 0; i < p->typedefs->node_len; ++i) { - if (strcmp(p->typedefs->node_items[i].name, name) == 0) { + for (int i = 0; i < p->typedefs->as.list->len; ++i) { + if (strcmp(p->typedefs->as.list->items[i].as.typedef_decl->name, name) == 0) { return i; } } @@ -370,10 +369,8 @@ static AstNode* parse_primary_expr(Parser* p) { } else if (t->kind == TokenKind_keyword_false) { return ast_new_int(0); } else if (t->kind == TokenKind_literal_str) { - AstNode* e = ast_new(AstNodeKind_str_expr); - e->node_idx = register_str_literal(p, t->value.string); - e->ty = type_new_static_string(strlen(t->value.string)); - return e; + return ast_new_str_expr(register_str_literal(p, t->value.string), + type_new_static_string(strlen(t->value.string))); } else if (t->kind == TokenKind_paren_l) { AstNode* e = parse_expr(p); expect(p, TokenKind_paren_r); @@ -382,14 +379,11 @@ static AstNode* parse_primary_expr(Parser* p) { const char* name = t->value.string; if (peek_token(p)->kind == TokenKind_paren_l) { - AstNode* e = ast_new(AstNodeKind_func_call); int func_idx = find_func(p, name); if (func_idx == -1) { fatal_error("%s:%d: undefined function: %s", t->loc.filename, t->loc.line, name); } - e->name = name; - e->ty = p->funcs.data[func_idx].ty->result; - return e; + return ast_new_func_call(name, p->funcs.data[func_idx].ty->result); } int lvar_idx = find_lvar(p, name); @@ -402,30 +396,21 @@ static AstNode* parse_primary_expr(Parser* p) { if (func_idx == -1) { fatal_error("%s:%d: undefined variable: %s", t->loc.filename, t->loc.line, name); } - AstNode* e = ast_new(AstNodeKind_func); - e->name = name; - e->ty = p->funcs.data[func_idx].ty; - return e; + return ast_new_func(name, p->funcs.data[func_idx].ty); } int enum_idx = enum_member_idx / 1000; int n = enum_member_idx % 1000; - AstNode* e = ast_new_int(p->enums->node_items[enum_idx].node_members->node_items[n].node_int_value); + AstNode* e = ast_new_int( + p->enums->as.list->items[enum_idx].as.enum_def->members->as.list->items[n].as.enum_member->value); e->ty = type_new(TypeKind_enum); e->ty->ref.defs = p->enums; e->ty->ref.index = enum_idx; return e; } - AstNode* e = ast_new(AstNodeKind_gvar); - e->name = name; - e->ty = p->gvars.data[gvar_idx].ty; - return e; + return ast_new_gvar(name, p->gvars.data[gvar_idx].ty); } - AstNode* e = ast_new(AstNodeKind_lvar); - e->name = name; - e->node_stack_offset = p->lvars.data[lvar_idx].stack_offset; - e->ty = p->lvars.data[lvar_idx].ty; - return e; + return ast_new_lvar(name, p->lvars.data[lvar_idx].stack_offset, p->lvars.data[lvar_idx].ty); } else { fatal_error("%s:%d: expected an expression, but got '%s'", t->loc.filename, t->loc.line, token_stringify(t)); } @@ -476,7 +461,7 @@ static AstNode* parse_postfix_expr(Parser* p) { if (consume_token_if(p, TokenKind_paren_l)) { AstNode* args = parse_arg_list(p); expect(p, TokenKind_paren_r); - ret->node_args = args; + ret->as.func_call->args = args; } else if (consume_token_if(p, TokenKind_bracket_l)) { AstNode* idx = parse_expr(p); expect(p, TokenKind_bracket_r); @@ -742,12 +727,7 @@ static AstNode* parse_logical_and_expr(Parser* p) { while (1) { if (consume_token_if(p, TokenKind_andand)) { AstNode* rhs = parse_bitwise_or_expr(p); - AstNode* e = ast_new(AstNodeKind_logical_expr); - e->node_op = TokenKind_andand; - e->node_lhs = lhs; - e->node_rhs = rhs; - e->ty = type_new(TypeKind_int); - lhs = e; + lhs = ast_new_logical_expr(TokenKind_andand, lhs, rhs); } else { break; } @@ -760,12 +740,7 @@ static AstNode* parse_logical_or_expr(Parser* p) { while (1) { if (consume_token_if(p, TokenKind_oror)) { AstNode* rhs = parse_logical_and_expr(p); - AstNode* e = ast_new(AstNodeKind_logical_expr); - e->node_op = TokenKind_oror; - e->node_lhs = lhs; - e->node_rhs = rhs; - e->ty = type_new(TypeKind_int); - lhs = e; + lhs = ast_new_logical_expr(TokenKind_oror, lhs, rhs); } else { break; } @@ -779,12 +754,7 @@ static AstNode* parse_conditional_expr(Parser* p) { AstNode* then_expr = parse_expr(p); expect(p, TokenKind_colon); AstNode* else_expr = parse_assignment_expr(p); - AstNode* ret = ast_new(AstNodeKind_cond_expr); - ret->node_cond = e; - ret->node_then = then_expr; - ret->node_else = else_expr; - ret->ty = then_expr->ty; - return ret; + return ast_new_cond_expr(e, then_expr, else_expr); } else { return e; } @@ -844,15 +814,12 @@ static AstNode* parse_expr(Parser* p) { static AstNode* parse_return_stmt(Parser* p) { expect(p, TokenKind_keyword_return); if (consume_token_if(p, TokenKind_semicolon)) { - return ast_new(AstNodeKind_return_stmt); + return ast_new_return_stmt(NULL); } AstNode* expr = parse_expr(p); expect(p, TokenKind_semicolon); - - AstNode* ret = ast_new(AstNodeKind_return_stmt); - ret->node_expr = expr; - return ret; + return ast_new_return_stmt(expr); } static AstNode* parse_if_stmt(Parser* p) { @@ -866,11 +833,7 @@ static AstNode* parse_if_stmt(Parser* p) { else_body = parse_stmt(p); } - AstNode* stmt = ast_new(AstNodeKind_if_stmt); - stmt->node_cond = cond; - stmt->node_then = then_body; - stmt->node_else = else_body; - return stmt; + return ast_new_if_stmt(cond, then_body, else_body); } // type-qualifier-list: @@ -916,9 +879,7 @@ static AstNode* parse_declarator_or_abstract_declarator_opt(Parser* p, Type* ty) AstNode* decl; if (peek_token(p)->kind == TokenKind_ident) { - decl = ast_new(AstNodeKind_declarator); - decl->name = parse_ident(p)->value.string; - decl->ty = ty; + decl = ast_new_declarator(parse_ident(p)->value.string, ty); } else if (peek_token(p)->kind == TokenKind_paren_l && !is_type_token(p, peek_token2(p))) { next_token(p); if (peek_token(p)->kind == TokenKind_paren_r) { @@ -929,8 +890,7 @@ static AstNode* parse_declarator_or_abstract_declarator_opt(Parser* p, Type* ty) decl = parse_declarator_or_abstract_declarator_opt(p, ty); expect(p, TokenKind_paren_r); } else { - decl = ast_new(AstNodeKind_declarator); - decl->ty = ty; + decl = ast_new_declarator(NULL, ty); } while (1) { @@ -953,9 +913,7 @@ static Type* parse_declaration_specifiers(Parser* p); // TODO attribute-specifier-sequence? declaration-specifiers abstract-declarator? static AstNode* parse_parameter_declaration(Parser* p) { if (consume_token_if(p, TokenKind_ellipsis)) { - AstNode* decl = ast_new(AstNodeKind_declarator); - decl->name = "..."; - return decl; + return ast_new_declarator("...", NULL); } Type* base_ty = parse_declaration_specifiers(p); @@ -987,22 +945,23 @@ static AstNode* parse_parameter_type_list(Parser* p) { AstNode* params = parse_parameter_list(p); bool has_void = false; - for (int i = 0; i < params->node_len; ++i) { - if (params->node_items[i].name && strcmp(params->node_items[i].name, "...") == 0) { - if (i != params->node_len - 1) { + for (int i = 0; i < params->as.list->len; ++i) { + if (params->as.list->items[i].as.declarator->name && + strcmp(params->as.list->items[i].as.declarator->name, "...") == 0) { + if (i != params->as.list->len - 1) { fatal_error("..."); } - --params->node_len; + --params->as.list->len; break; } - has_void |= params->node_items[i].ty->kind == TypeKind_void; + has_void |= params->as.list->items[i].ty->kind == TypeKind_void; } if (has_void) { - if (params->node_len != 1) { + if (params->as.list->len != 1) { fatal_error("invalid use of void param"); } - params->node_len = 0; + params->as.list->len = 0; } return params; @@ -1057,16 +1016,13 @@ static AstNode* parse_declarator(Parser* p, Type* ty); static AstNode* parse_direct_declarator(Parser* p, Type* ty) { AstNode* decl; if (peek_token(p)->kind == TokenKind_ident) { - decl = ast_new(AstNodeKind_declarator); - decl->name = parse_ident(p)->value.string; - decl->ty = ty; + decl = ast_new_declarator(parse_ident(p)->value.string, ty); } else if (peek_token(p)->kind == TokenKind_paren_l && !is_type_token(p, peek_token2(p))) { next_token(p); decl = parse_declarator(p, ty); expect(p, TokenKind_paren_r); } else { - decl = ast_new(AstNodeKind_declarator); - decl->ty = ty; + decl = ast_new_declarator(NULL, ty); } while (1) { @@ -1079,10 +1035,7 @@ static AstNode* parse_direct_declarator(Parser* p, Type* ty) { } } - AstNode* ret = ast_new(AstNodeKind_declarator); - ret->name = decl->name; - ret->ty = decl->ty; - return ret; + return ast_new_declarator(decl->as.declarator->name, decl->ty); } // declarator: @@ -1104,11 +1057,9 @@ static AstNode* parse_initializer(Parser* p) { // declarator '=' initializer static AstNode* parse_init_declarator(Parser* p, Type* ty) { AstNode* decl = parse_declarator(p, ty); - AstNode* init = NULL; if (consume_token_if(p, TokenKind_assign)) { - init = parse_initializer(p); + decl->as.declarator->init = parse_initializer(p); } - decl->node_init = init; return decl; } @@ -1131,7 +1082,7 @@ static AstNode* parse_init_declarator_list(Parser* p, Type* ty) { } // Immediately declare to allow following initializer to access previous variables. For example, // int a = 1, b = a; - declare_func_or_var(p, &list->node_items[list->node_len - 1]); + declare_func_or_var(p, &list->as.list->items[list->as.list->len - 1]); } return list; } @@ -1140,7 +1091,7 @@ static AstNode* parse_var_decl(Parser* p) { Type* base_ty = parse_type_name(p); AstNode* decls = parse_init_declarator_list(p, base_ty); expect(p, TokenKind_semicolon); - declare_func_or_var(p, &decls->node_items[decls->node_len - 1]); + declare_func_or_var(p, &decls->as.list->items[decls->as.list->len - 1]); return decls; } @@ -1155,10 +1106,10 @@ static AstNode* parse_for_stmt(Parser* p) { if (is_type_token(p, peek_token(p))) { AstNode* decls = parse_var_decl(p); AstNode* initializers = ast_new_list(1); - for (int i = 0; i < decls->node_len; i++) { - AstNode* initializer = decls->node_items[i].node_expr; - if (initializer) { - ast_append(initializers, initializer); + for (int i = 0; i < decls->as.list->len; i++) { + AstNode* item = &decls->as.list->items[i]; + if (item->kind == AstNodeKind_expr_stmt) { + ast_append(initializers, item->as.expr_stmt->expr); } } init = initializers; @@ -1181,13 +1132,7 @@ static AstNode* parse_for_stmt(Parser* p) { expect(p, TokenKind_paren_r); AstNode* body = parse_stmt(p); leave_scope(p); - - AstNode* stmt = ast_new(AstNodeKind_for_stmt); - stmt->node_cond = cond; - stmt->node_init = init; - stmt->node_update = update; - stmt->node_body = body; - return stmt; + return ast_new_for_stmt(init, cond, update, body); } static AstNode* parse_while_stmt(Parser* p) { @@ -1196,11 +1141,7 @@ static AstNode* parse_while_stmt(Parser* p) { AstNode* cond = parse_expr(p); expect(p, TokenKind_paren_r); AstNode* body = parse_stmt(p); - - AstNode* stmt = ast_new(AstNodeKind_for_stmt); - stmt->node_cond = cond; - stmt->node_body = body; - return stmt; + return ast_new_for_stmt(NULL, cond, NULL, body); } static AstNode* parse_do_while_stmt(Parser* p) { @@ -1212,10 +1153,7 @@ static AstNode* parse_do_while_stmt(Parser* p) { expect(p, TokenKind_paren_r); expect(p, TokenKind_semicolon); - AstNode* stmt = ast_new(AstNodeKind_do_while_stmt); - stmt->node_cond = cond; - stmt->node_body = body; - return stmt; + return ast_new_do_while_stmt(cond, body); } static AstNode* parse_switch_stmt(Parser* p) { @@ -1226,15 +1164,13 @@ static AstNode* parse_switch_stmt(Parser* p) { AstNode* tmp_var = generate_temporary_lvar(p, expr->ty); AstNode* assignment = ast_new_assign_expr(TokenKind_assign, tmp_var, expr); - AstNode* assign_stmt = ast_new(AstNodeKind_expr_stmt); - assign_stmt->node_expr = assignment; + AstNode* assign_stmt = ast_new_expr_stmt(assignment); - AstNode* switch_stmt = ast_new(AstNodeKind_switch_stmt); - switch_stmt->node_expr = tmp_var; + AstNode* switch_stmt = ast_new_switch_stmt(tmp_var); AstNode* prev_switch = p->current_switch; p->current_switch = switch_stmt; - switch_stmt->node_body = parse_stmt(p); + switch_stmt->as.switch_stmt->body = parse_stmt(p); p->current_switch = prev_switch; AstNode* list = ast_new_list(2); @@ -1246,21 +1182,19 @@ static AstNode* parse_switch_stmt(Parser* p) { static AstNode* parse_break_stmt(Parser* p) { expect(p, TokenKind_keyword_break); expect(p, TokenKind_semicolon); - return ast_new(AstNodeKind_break_stmt); + return ast_new_break_stmt(); } static AstNode* parse_continue_stmt(Parser* p) { expect(p, TokenKind_keyword_continue); expect(p, TokenKind_semicolon); - return ast_new(AstNodeKind_continue_stmt); + return ast_new_continue_stmt(); } static AstNode* parse_expr_stmt(Parser* p) { AstNode* e = parse_expr(p); expect(p, TokenKind_semicolon); - AstNode* stmt = ast_new(AstNodeKind_expr_stmt); - stmt->node_expr = e; - return stmt; + return ast_new_expr_stmt(e); } static AstNode* parse_block_stmt(Parser* p) { @@ -1278,7 +1212,7 @@ static AstNode* parse_block_stmt(Parser* p) { static AstNode* parse_empty_stmt(Parser* p) { consume_token_if(p, TokenKind_semicolon); - return ast_new(AstNodeKind_nop); + return ast_new_nop(); } static AstNode* parse_stmt(Parser* p) { @@ -1293,10 +1227,7 @@ static AstNode* parse_stmt(Parser* p) { expect(p, TokenKind_colon); AstNode* stmt = parse_stmt(p); - AstNode* case_label = ast_new(AstNodeKind_case_label); - case_label->node_int_value = eval(value); - case_label->node_body = stmt; - return case_label; + return ast_new_case_label(eval(value), stmt); } else if (t->kind == TokenKind_keyword_default) { if (!p->current_switch) { fatal_error("%s:%d: 'default' label not within a switch statement", t->loc.filename, t->loc.line); @@ -1305,9 +1236,7 @@ static AstNode* parse_stmt(Parser* p) { expect(p, TokenKind_colon); AstNode* stmt = parse_stmt(p); - AstNode* default_label = ast_new(AstNodeKind_default_label); - default_label->node_body = stmt; - return default_label; + return ast_new_default_label(stmt); } else if (t->kind == TokenKind_keyword_return) { return parse_return_stmt(p); } else if (t->kind == TokenKind_keyword_if) { @@ -1329,9 +1258,7 @@ static AstNode* parse_stmt(Parser* p) { Token* label_token = expect(p, TokenKind_ident); expect(p, TokenKind_semicolon); - AstNode* goto_stmt = ast_new(AstNodeKind_goto_stmt); - goto_stmt->name = label_token->value.string; - return goto_stmt; + return ast_new_goto_stmt(label_token->value.string); } else if (t->kind == TokenKind_brace_l) { return parse_block_stmt(p); } else if (t->kind == TokenKind_semicolon) { @@ -1344,10 +1271,7 @@ static AstNode* parse_stmt(Parser* p) { expect(p, TokenKind_colon); AstNode* stmt = parse_stmt(p); - AstNode* label_stmt = ast_new(AstNodeKind_label_stmt); - label_stmt->name = label_token->value.string; - label_stmt->node_body = stmt; - return label_stmt; + return ast_new_label_stmt(label_token->value.string, stmt); } else { return parse_expr_stmt(p); } @@ -1357,8 +1281,8 @@ static void register_params(Parser* p, AstNode* params) { int gp_regs = 6; int pass_by_reg_offset = 8; int pass_by_stack_offset = -16; - for (int i = 0; i < params->node_len; ++i) { - AstNode* param = ¶ms->node_items[i]; + for (int i = 0; i < params->as.list->len; ++i) { + AstNode* param = ¶ms->as.list->items[i]; int ty_size = type_sizeof(param->ty); int required_gp_regs; if (ty_size <= 8) { @@ -1381,8 +1305,12 @@ static void register_params(Parser* p, AstNode* params) { stack_offset = pass_by_reg_offset; pass_by_reg_offset += to_aligned(ty_size, 8); } - param->node_stack_offset = stack_offset; - add_lvar(p, param->name, param->ty, stack_offset); + const char* name = param->as.declarator->name; + param->kind = AstNodeKind_param; + param->as.param = calloc(1, sizeof(ParamNode)); + param->as.param->name = name; + param->as.param->stack_offset = stack_offset; + add_lvar(p, name, param->ty, stack_offset); } } @@ -1393,11 +1321,12 @@ static void register_func(Parser* p, const char* name, Type* ty) { } static void declare_func_or_var(Parser* p, AstNode* decl) { + const char* name = decl->as.declarator->name; if (decl->ty->kind == TypeKind_func) { // TODO: refactor decl->ty->storage_class = decl->ty->result->storage_class; decl->ty->result->storage_class = StorageClass_unspecified; - register_func(p, decl->name, decl->ty); + register_func(p, name, decl->ty); decl->kind = AstNodeKind_func_decl; } else { if (type_is_unsized(decl->ty)) { @@ -1405,26 +1334,24 @@ static void declare_func_or_var(Parser* p, AstNode* decl) { } if (p->scope) { - if (find_lvar_in_current_scope(p, decl->name) != -1) { + if (find_lvar_in_current_scope(p, name) != -1) { // TODO: use name's location. - fatal_error("%s:%d: '%s' redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, decl->name); + fatal_error("%s:%d: '%s' redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, name); } - int stack_offset = add_lvar(p, decl->name, decl->ty, calc_lvar_stack_offset(p, decl->ty)); + int stack_offset = add_lvar(p, name, decl->ty, calc_lvar_stack_offset(p, decl->ty)); - if (decl->node_init) { - AstNode* lhs = ast_new(AstNodeKind_lvar); - lhs->name = decl->name; - lhs->node_stack_offset = stack_offset; - lhs->ty = decl->ty; - AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, decl->node_init); + if (decl->as.declarator->init) { + AstNode* lhs = ast_new_lvar(name, stack_offset, decl->ty); + AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, decl->as.declarator->init); decl->kind = AstNodeKind_expr_stmt; - decl->node_expr = assign; + decl->as.expr_stmt = calloc(1, sizeof(ExprStmtNode)); + decl->as.expr_stmt->expr = assign; } else { decl->kind = AstNodeKind_nop; } } else { - if (find_gvar(p, decl->name) != -1) { - fatal_error("declare_func_or_var: %s redeclared", decl->name); + if (find_gvar(p, name) != -1) { + fatal_error("declare_func_or_var: %s redeclared", name); } // TODO: refactor Type* base_ty = decl->ty; @@ -1435,32 +1362,35 @@ static void declare_func_or_var(Parser* p, AstNode* decl) { base_ty->storage_class = StorageClass_unspecified; GlobalVar* gvar = gvars_push_new(&p->gvars); - gvar->name = decl->name; + gvar->name = name; gvar->ty = decl->ty; if (decl->ty->storage_class == StorageClass_extern) { decl->kind = AstNodeKind_nop; } else { + AstNode* init_expr = decl->as.declarator ? decl->as.declarator->init : NULL; decl->kind = AstNodeKind_gvar_decl; - decl->node_expr = decl->node_init; + decl->as.gvar_decl = calloc(1, sizeof(GvarDeclNode)); + decl->as.gvar_decl->name = name; + decl->as.gvar_decl->expr = init_expr; } } } } static AstNode* parse_func_def(Parser* p, AstNode* decls) { - if (decls->node_len != 1) { + if (decls->as.list->len != 1) { fatal_error("parse_func_def: invalid syntax"); } - Type* ty = decls->node_items[0].ty; + Type* ty = decls->as.list->items[0].ty; Type* base_ty = ty->result; while (base_ty->base) { base_ty = base_ty->base; } ty->storage_class = base_ty->storage_class; base_ty->storage_class = StorageClass_unspecified; - const char* name = decls->node_items[0].name; + const char* name = decls->as.list->items[0].as.declarator->name; AstNode* params = ty->params; register_func(p, name, ty); @@ -1469,21 +1399,14 @@ static AstNode* parse_func_def(Parser* p, AstNode* decls) { AstNode* body = parse_block_stmt(p); leave_func(p); - AstNode* func = ast_new(AstNodeKind_func_def); - func->ty = ty; - func->name = name; - func->node_params = params; - func->node_body = body; - if (p->lvars.len == 0) { - func->node_stack_size = 0; - } else { - int stack_size = p->lvars.data[p->lvars.len - 1].stack_offset + type_sizeof(p->lvars.data[p->lvars.len - 1].ty); + int stack_size = 0; + if (p->lvars.len != 0) { + stack_size = p->lvars.data[p->lvars.len - 1].stack_offset + type_sizeof(p->lvars.data[p->lvars.len - 1].ty); if (stack_size < 0) { stack_size = 0; } - func->node_stack_size = stack_size; } - return func; + return ast_new_func_def(name, ty, params, body, stack_size); } // member-declarator: @@ -1523,8 +1446,11 @@ static AstNode* parse_member_declaration(Parser* p) { expect(p, TokenKind_semicolon); - for (int i = 0; i < decls->node_len; i++) { - decls->node_items[i].kind = AstNodeKind_struct_member; + for (int i = 0; i < decls->as.list->len; i++) { + const char* member_name = decls->as.list->items[i].as.declarator->name; + decls->as.list->items[i].kind = AstNodeKind_struct_member; + decls->as.list->items[i].as.struct_member = calloc(1, sizeof(StructMemberNode)); + decls->as.list->items[i].as.struct_member->name = member_name; } return decls; } @@ -1535,44 +1461,36 @@ static AstNode* parse_member_declaration_list(Parser* p) { AstNode* members = ast_new_list(4); while (peek_token(p)->kind != TokenKind_brace_r) { AstNode* decls = parse_member_declaration(p); - for (int i = 0; i < decls->node_len; i++) { - ast_append(members, &decls->node_items[i]); + for (int i = 0; i < decls->as.list->len; i++) { + ast_append(members, &decls->as.list->items[i]); } } return members; } -static AstNode* parse_enum_member(Parser* p) { +static AstNode* parse_enum_member(Parser* p, int next_value) { const Token* name = parse_ident(p); - AstNode* member = ast_new(AstNodeKind_enum_member); - member->name = name->value.string; - + int value; if (consume_token_if(p, TokenKind_assign)) { - member->node_expr = parse_constant_expression(p); + AstNode* expr = parse_constant_expression(p); + value = eval(expr); + } else { + value = next_value; } - - return member; + return ast_new_enum_member(name->value.string, value); } static void parse_enum_members(Parser* p, int enum_idx) { int next_value = 0; AstNode* list = ast_new_list(16); - if (!p->enums->node_items[enum_idx].node_members) { - p->enums->node_items[enum_idx].node_members = list; + if (!p->enums->as.list->items[enum_idx].as.enum_def->members) { + p->enums->as.list->items[enum_idx].as.enum_def->members = list; } while (peek_token(p)->kind != TokenKind_brace_r) { - AstNode* member = parse_enum_member(p); - - if (member->node_expr) { - member->node_int_value = eval(member->node_expr); - member->node_expr = NULL; - next_value = member->node_int_value; - } else { - member->node_int_value = next_value; - } - ++next_value; + AstNode* member = parse_enum_member(p, next_value); + next_value = member->as.enum_member->value + 1; ast_append(list, member); @@ -1584,12 +1502,10 @@ static void parse_enum_members(Parser* p, int enum_idx) { void parse_typedef_decl(Parser* p, AstNode* decls) { expect(p, TokenKind_semicolon); - for (int i = 0; i < decls->node_len; ++i) { - AstNode* decl = &decls->node_items[i]; + for (int i = 0; i < decls->as.list->len; ++i) { + AstNode* decl = &decls->as.list->items[i]; - AstNode* typedef_ = ast_new(AstNodeKind_typedef_decl); - typedef_->name = decl->name; - typedef_->ty = decl->ty; + AstNode* typedef_ = ast_new_typedef_decl(decl->as.declarator->name, decl->ty); ast_append(p->typedefs, typedef_); } } @@ -1629,10 +1545,9 @@ static Type* parse_struct_specifier(Parser* p) { return ty; } else { // TODO - AstNode* new_struct = ast_new(AstNodeKind_struct_def); - new_struct->name = name->value.string; + AstNode* new_struct = ast_new_struct_def(name->value.string); ast_append(p->structs, new_struct); - struct_idx = p->structs->node_len - 1; + struct_idx = p->structs->as.list->len - 1; Type* ty = type_new(TypeKind_struct); ty->ref.defs = p->structs; @@ -1642,20 +1557,19 @@ static Type* parse_struct_specifier(Parser* p) { } int struct_idx = find_struct(p, name->value.string); - if (struct_idx != -1 && p->structs->node_items[struct_idx].node_members) { + if (struct_idx != -1 && p->structs->as.list->items[struct_idx].as.struct_def->members) { fatal_error("%s:%d: struct %s redefined", name->loc.filename, name->loc.line, name->value.string); } if (struct_idx == -1) { - AstNode* new_struct = ast_new(AstNodeKind_struct_def); - new_struct->name = name->value.string; + AstNode* new_struct = ast_new_struct_def(name->value.string); ast_append(p->structs, new_struct); - struct_idx = p->structs->node_len - 1; + struct_idx = p->structs->as.list->len - 1; } AstNode* members = parse_member_declaration_list(p); expect(p, TokenKind_brace_r); - p->structs->node_items[struct_idx].node_members = members; + p->structs->as.list->items[struct_idx].as.struct_def->members = members; Type* ty = type_new(TypeKind_struct); ty->ref.defs = p->structs; @@ -1692,10 +1606,9 @@ static Type* parse_union_specifier(Parser* p) { return ty; } else { // TODO - AstNode* new_union = ast_new(AstNodeKind_union_def); - new_union->name = name->value.string; + AstNode* new_union = ast_new_union_def(name->value.string); ast_append(p->unions, new_union); - union_idx = p->unions->node_len - 1; + union_idx = p->unions->as.list->len - 1; Type* ty = type_new(TypeKind_union); ty->ref.defs = p->unions; @@ -1705,20 +1618,19 @@ static Type* parse_union_specifier(Parser* p) { } int union_idx = find_union(p, name->value.string); - if (union_idx != -1 && p->unions->node_items[union_idx].node_members) { + if (union_idx != -1 && p->unions->as.list->items[union_idx].as.union_def->members) { fatal_error("%s:%d: union %s redefined", name->loc.filename, name->loc.line, name->value.string); } if (union_idx == -1) { - AstNode* new_union = ast_new(AstNodeKind_union_def); - new_union->name = name->value.string; + AstNode* new_union = ast_new_union_def(name->value.string); ast_append(p->unions, new_union); - union_idx = p->unions->node_len - 1; + union_idx = p->unions->as.list->len - 1; } AstNode* members = parse_member_declaration_list(p); expect(p, TokenKind_brace_r); - p->unions->node_items[union_idx].node_members = members; + p->unions->as.list->items[union_idx].as.union_def->members = members; Type* ty = type_new(TypeKind_union); ty->ref.defs = p->unions; @@ -1755,10 +1667,9 @@ static Type* parse_enum_specifier(Parser* p) { return ty; } else { // TODO - AstNode* new_enum = ast_new(AstNodeKind_enum_def); - new_enum->name = name->value.string; + AstNode* new_enum = ast_new_enum_def(name->value.string); ast_append(p->enums, new_enum); - enum_idx = p->enums->node_len - 1; + enum_idx = p->enums->as.list->len - 1; Type* ty = type_new(TypeKind_enum); ty->ref.defs = p->enums; @@ -1768,15 +1679,14 @@ static Type* parse_enum_specifier(Parser* p) { } int enum_idx = find_enum(p, name->value.string); - if (enum_idx != -1 && p->enums->node_items[enum_idx].node_members) { + if (enum_idx != -1 && p->enums->as.list->items[enum_idx].as.enum_def->members) { fatal_error("%s:%d: enum %s redefined", name->loc.filename, name->loc.line, name->value.string); } if (enum_idx == -1) { - AstNode* new_enum = ast_new(AstNodeKind_enum_def); - new_enum->name = name->value.string; + AstNode* new_enum = ast_new_enum_def(name->value.string); ast_append(p->enums, new_enum); - enum_idx = p->enums->node_len - 1; + enum_idx = p->enums->as.list->len - 1; } parse_enum_members(p, enum_idx); @@ -2104,7 +2014,7 @@ static Type* parse_declaration_specifiers(Parser* p) { } next_token(p); int typedef_idx = find_typedef(p, tok->value.string); - ty = p->typedefs->node_items[typedef_idx].ty; + ty = p->typedefs->as.list->items[typedef_idx].ty; type_specifiers += TypeSpecifierMask_typedef_name; } // type-specifier-qualifier > type-qualifier @@ -2281,7 +2191,7 @@ static Type* parse_specifier_qualifier_list(Parser* p) { } next_token(p); int typedef_idx = find_typedef(p, tok->value.string); - ty = p->typedefs->node_items[typedef_idx].ty; + ty = p->typedefs->as.list->items[typedef_idx].ty; type_specifiers += TypeSpecifierMask_typedef_name; } // type-specifier-qualifier > type-qualifier @@ -2348,7 +2258,7 @@ static AstNode* parse_toplevel(Parser* p) { return NULL; } else { expect(p, TokenKind_semicolon); - declare_func_or_var(p, &decls->node_items[decls->node_len - 1]); + declare_func_or_var(p, &decls->as.list->items[decls->as.list->len - 1]); return decls; } } @@ -2366,9 +2276,9 @@ Program* parse(TokenArray* tokens) { } else if (n->kind == AstNodeKind_gvar_decl) { ast_append(vars, n); } else if (n->kind == AstNodeKind_list) { - for (int i = 0; i < n->node_len; ++i) { - if (n->node_items[i].kind == AstNodeKind_gvar_decl) - ast_append(vars, &n->node_items[i]); + for (int i = 0; i < n->as.list->len; ++i) { + if (n->as.list->items[i].kind == AstNodeKind_gvar_decl) + ast_append(vars, &n->as.list->items[i]); } } } @@ -2379,71 +2289,79 @@ Program* parse(TokenArray* tokens) { return prog; } +static int eval_binary_expr(int op, int v1, int v2) { + if (op == TokenKind_andand) { + return v1 && v2; + } else if (op == TokenKind_oror) { + return v1 || v2; + } else if (op == TokenKind_plus) { + return v1 + v2; + } else if (op == TokenKind_minus) { + return v1 - v2; + } else if (op == TokenKind_star) { + return v1 * v2; + } else if (op == TokenKind_slash) { + if (v2 == 0) { + fatal_error("eval: division by zero"); + } + return v1 / v2; + } else if (op == TokenKind_percent) { + if (v2 == 0) { + fatal_error("eval: division by zero"); + } + return v1 % v2; + } else if (op == TokenKind_eq) { + return v1 == v2; + } else if (op == TokenKind_ne) { + return v1 != v2; + } else if (op == TokenKind_lt) { + return v1 < v2; + } else if (op == TokenKind_le) { + return v1 <= v2; + } else if (op == TokenKind_lshift) { + return v1 << v2; + } else if (op == TokenKind_rshift) { + return v1 >> v2; + } else if (op == TokenKind_and) { + return v1 & v2; + } else if (op == TokenKind_or) { + return v1 | v2; + } else if (op == TokenKind_xor) { + return v1 ^ v2; + } else { + unimplemented(); + } +} + static int eval(AstNode* e) { if (e->kind == AstNodeKind_int_expr) { - return e->node_int_value; + return e->as.int_expr->value; } else if (e->kind == AstNodeKind_unary_expr) { - int v = eval(e->node_operand); - if (e->node_op == TokenKind_not) { + int v = eval(e->as.unary_expr->operand); + if (e->as.unary_expr->op == TokenKind_not) { return !v; - } else if (e->node_op == TokenKind_minus) { + } else if (e->as.unary_expr->op == TokenKind_minus) { return -v; } else { unimplemented(); } - } else if (e->kind == AstNodeKind_binary_expr || e->kind == AstNodeKind_logical_expr) { - int v1 = eval(e->node_lhs); - int v2 = eval(e->node_rhs); - if (e->node_op == TokenKind_andand) { - return v1 && v2; - } else if (e->node_op == TokenKind_oror) { - return v1 || v2; - } else if (e->node_op == TokenKind_plus) { - return v1 + v2; - } else if (e->node_op == TokenKind_minus) { - return v1 - v2; - } else if (e->node_op == TokenKind_star) { - return v1 * v2; - } else if (e->node_op == TokenKind_slash) { - if (v2 == 0) { - fatal_error("eval: division by zero"); - } - return v1 / v2; - } else if (e->node_op == TokenKind_percent) { - if (v2 == 0) { - fatal_error("eval: division by zero"); - } - return v1 % v2; - } else if (e->node_op == TokenKind_eq) { - return v1 == v2; - } else if (e->node_op == TokenKind_ne) { - return v1 != v2; - } else if (e->node_op == TokenKind_lt) { - return v1 < v2; - } else if (e->node_op == TokenKind_le) { - return v1 <= v2; - } else if (e->node_op == TokenKind_lshift) { - return v1 << v2; - } else if (e->node_op == TokenKind_rshift) { - return v1 >> v2; - } else if (e->node_op == TokenKind_and) { - return v1 & v2; - } else if (e->node_op == TokenKind_or) { - return v1 | v2; - } else if (e->node_op == TokenKind_xor) { - return v1 ^ v2; - } else { - unimplemented(); - } + } else if (e->kind == AstNodeKind_binary_expr) { + int v1 = eval(e->as.binary_expr->lhs); + int v2 = eval(e->as.binary_expr->rhs); + return eval_binary_expr(e->as.binary_expr->op, v1, v2); + } else if (e->kind == AstNodeKind_logical_expr) { + int v1 = eval(e->as.logical_expr->lhs); + int v2 = eval(e->as.logical_expr->rhs); + return eval_binary_expr(e->as.logical_expr->op, v1, v2); } else if (e->kind == AstNodeKind_cond_expr) { - int cond = eval(e->node_cond); + int cond = eval(e->as.cond_expr->cond); if (cond) { - return eval(e->node_then); + return eval(e->as.cond_expr->then); } else { - return eval(e->node_else); + return eval(e->as.cond_expr->else_); } } else if (e->kind == AstNodeKind_cast_expr) { - return eval(e->node_operand); + return eval(e->as.cast_expr->operand); } else { unimplemented(); } |
