diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-08-22 23:28:25 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-08-22 23:28:25 +0900 |
| commit | 9c202a496e75903fe37e5c19cb97c98eba6e35f2 (patch) | |
| tree | 52de494a4717a3c30c4bacb9dd9b91980be2a575 /src/ast.c | |
| parent | 0ac6ac95283735dd70ebf55b26ef78a4c32c31de (diff) | |
| download | ducc-9c202a496e75903fe37e5c19cb97c98eba6e35f2.tar.gz ducc-9c202a496e75903fe37e5c19cb97c98eba6e35f2.tar.zst ducc-9c202a496e75903fe37e5c19cb97c98eba6e35f2.zip | |
chore: move *.c and *.h files to src/
Diffstat (limited to 'src/ast.c')
| -rw-r--r-- | src/ast.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/src/ast.c b/src/ast.c new file mode 100644 index 0000000..66f7cc2 --- /dev/null +++ b/src/ast.c @@ -0,0 +1,475 @@ +enum TypeKind { + TypeKind_unknown, + + TypeKind_char, + TypeKind_short, + TypeKind_int, + TypeKind_long, + TypeKind_void, + TypeKind_ptr, + TypeKind_array, + TypeKind_enum, + TypeKind_struct, + TypeKind_union, +}; +typedef enum TypeKind TypeKind; + +const char* type_kind_stringify(TypeKind k) { + if (k == TypeKind_unknown) + return "<unknown>"; + else if (k == TypeKind_char) + return "char"; + else if (k == TypeKind_short) + return "short"; + else if (k == TypeKind_int) + return "int"; + else if (k == TypeKind_long) + return "long"; + else if (k == TypeKind_void) + return "void"; + else if (k == TypeKind_ptr) + return "<pointer>"; + else if (k == TypeKind_array) + return "<array>"; + else if (k == TypeKind_enum) + return "enum"; + else if (k == TypeKind_struct) + return "struct"; + else if (k == TypeKind_union) + return "union"; + else + unreachable(); +} + +struct AstNode; + +struct Type { + TypeKind kind; + // Check `base` instead of `kind` to test if the type is an array or a pointer. + struct Type* base; + int array_size; + struct AstNode* def; +}; +typedef struct Type Type; + +void type_dump(Type* ty) { + fprintf(stderr, "Type {\n"); + fprintf(stderr, " kind = %s\n", type_kind_stringify(ty->kind)); + fprintf(stderr, "}\n"); +} + +Type* type_new(TypeKind kind) { + Type* ty = calloc(1, sizeof(Type)); + ty->kind = kind; + return ty; +} + +Type* type_new_ptr(Type* base) { + Type* ty = calloc(1, sizeof(Type)); + ty->kind = TypeKind_ptr; + ty->base = base; + return ty; +} + +Type* type_new_array(Type* elem, int size) { + Type* ty = calloc(1, sizeof(Type)); + ty->kind = TypeKind_array; + ty->base = elem; + ty->array_size = size; + return ty; +} + +Type* type_new_static_string(int len) { + return type_new_array(type_new(TypeKind_char), len + 1); +} + +Type* type_array_to_ptr(Type* ty) { + return type_new_ptr(ty->base); +} + +BOOL type_is_unsized(Type* ty) { + return ty->kind == TypeKind_void; +} + +int type_sizeof_struct(Type* ty); +int type_sizeof_union(Type* ty); +int type_alignof_struct(Type* ty); +int type_alignof_union(Type* ty); +int type_offsetof(Type* ty, const char* name); +Type* type_member_typeof(Type* ty, const char* name); + +int type_sizeof(Type* ty) { + if (type_is_unsized(ty)) { + fatal_error("type_sizeof: type size cannot be determined"); + } + + if (ty->kind == TypeKind_ptr) + return 8; + else if (ty->kind == TypeKind_char) + return 1; + else if (ty->kind == TypeKind_short) + return 2; + else if (ty->kind == TypeKind_int) + return 4; + else if (ty->kind == TypeKind_long) + return 8; + else if (ty->kind == TypeKind_enum) + return 4; + else if (ty->kind == TypeKind_array) + return type_sizeof(ty->base) * ty->array_size; + else if (ty->kind == TypeKind_struct) + return type_sizeof_struct(ty); + else if (ty->kind == TypeKind_union) + return type_sizeof_union(ty); + else + unreachable(); +} + +int type_alignof(Type* ty) { + if (type_is_unsized(ty)) { + fatal_error("type_alignof: type size cannot be determined"); + } + + if (ty->kind == TypeKind_ptr) + return 8; + else if (ty->kind == TypeKind_char) + return 1; + else if (ty->kind == TypeKind_short) + return 2; + else if (ty->kind == TypeKind_int) + return 4; + else if (ty->kind == TypeKind_long) + return 8; + else if (ty->kind == TypeKind_enum) + return 4; + else if (ty->kind == TypeKind_array) + return type_alignof(ty->base); + else if (ty->kind == TypeKind_struct) + return type_alignof_struct(ty); + else if (ty->kind == TypeKind_union) + return type_alignof_union(ty); + else + unreachable(); +} + +int to_aligned(int n, int a) { + return (n + a - 1) / a * a; +} + +enum AstNodeKind { + AstNodeKind_unknown, + AstNodeKind_nop, + + AstNodeKind_assign_expr, + AstNodeKind_binary_expr, + AstNodeKind_break_stmt, + AstNodeKind_cond_expr, + AstNodeKind_continue_stmt, + AstNodeKind_deref_expr, + AstNodeKind_do_while_stmt, + AstNodeKind_enum_def, + AstNodeKind_enum_member, + AstNodeKind_expr_stmt, + AstNodeKind_for_stmt, + AstNodeKind_func_call, + AstNodeKind_func_decl, + AstNodeKind_func_def, + AstNodeKind_gvar, + AstNodeKind_gvar_decl, + AstNodeKind_if_stmt, + AstNodeKind_int_expr, + AstNodeKind_list, + AstNodeKind_logical_expr, + AstNodeKind_lvar, + AstNodeKind_lvar_decl, + AstNodeKind_param, + AstNodeKind_ref_expr, + AstNodeKind_return_stmt, + AstNodeKind_str_expr, + AstNodeKind_struct_decl, + AstNodeKind_struct_def, + AstNodeKind_struct_member, + AstNodeKind_type, + AstNodeKind_typedef_decl, + AstNodeKind_unary_expr, + AstNodeKind_union_decl, + AstNodeKind_union_def, + AstNodeKind_union_member, + + // Intermediate ASTs: they are used only in parsing, not for parse result. + AstNodeKind_declarator, +}; +typedef enum AstNodeKind AstNodeKind; + +#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 + +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; +}; +typedef struct AstNode AstNode; + +struct Program { + AstNode* funcs; + AstNode* vars; + const char** str_literals; +}; +typedef struct Program Program; + +AstNode* ast_new(AstNodeKind kind) { + AstNode* ast = calloc(1, sizeof(AstNode)); + ast->kind = kind; + return ast; +} + +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)); + return list; +} + +void ast_append(AstNode* list, AstNode* item) { + if (list->kind != AstNodeKind_list) { + fatal_error("ast_append: ast is not a list"); + } + 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)); + } + memcpy(list->node_items + list->node_len, item, sizeof(AstNode)); + ++list->node_len; +} + +AstNode* ast_new_int(int v) { + AstNode* e = ast_new(AstNodeKind_int_expr); + e->node_int_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->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; + if (op == TokenKind_plus) { + if (lhs->ty->kind == TypeKind_ptr) { + e->ty = lhs->ty; + } else if (lhs->ty->kind == TypeKind_array) { + e->ty = type_array_to_ptr(lhs->ty); + } else if (rhs->ty->kind == TypeKind_ptr) { + e->ty = rhs->ty; + } else if (rhs->ty->kind == TypeKind_array) { + e->ty = type_array_to_ptr(rhs->ty); + } else { + e->ty = type_new(TypeKind_int); + } + } else if (op == TokenKind_minus) { + if (lhs->ty->kind == TypeKind_ptr) { + e->ty = lhs->ty; + } else if (lhs->ty->kind == TypeKind_array) { + e->ty = type_array_to_ptr(lhs->ty); + } else { + e->ty = type_new(TypeKind_int); + } + } else { + e->ty = type_new(TypeKind_int); + } + return e; +} + +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->ty = lhs->ty; + return e; +} + +AstNode* ast_new_assign_add_expr(AstNode* lhs, AstNode* rhs) { + if (lhs->ty->base) { + rhs = ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->base))); + } else if (rhs->ty->base) { + lhs = ast_new_binary_expr(TokenKind_star, lhs, ast_new_int(type_sizeof(rhs->ty->base))); + } + return ast_new_assign_expr(TokenKind_assign_add, lhs, rhs); +} + +AstNode* ast_new_assign_sub_expr(AstNode* lhs, AstNode* rhs) { + if (lhs->ty->base) { + rhs = ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->base))); + } + return ast_new_assign_expr(TokenKind_assign_sub, lhs, rhs); +} + +AstNode* ast_new_ref_expr(AstNode* operand) { + AstNode* e = ast_new(AstNodeKind_ref_expr); + e->node_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->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->ty = type_member_typeof(obj->ty->base, name); + e->node_operand->ty = type_new_ptr(e->ty); + return e; +} + +int type_sizeof_struct(Type* ty) { + int next_offset = 0; + int struct_align = 0; + + for (int i = 0; i < ty->def->node_members->node_len; ++i) { + AstNode* member = ty->def->node_members->node_items + i; + int size = type_sizeof(member->ty); + int align = type_alignof(member->ty); + + next_offset = to_aligned(next_offset, align); + next_offset += size; + if (struct_align < align) { + struct_align = align; + } + } + return to_aligned(next_offset, struct_align); +} + +int type_sizeof_union(Type* ty) { + int union_size = 0; + int union_align = 0; + + for (int i = 0; i < ty->def->node_members->node_len; ++i) { + AstNode* member = ty->def->node_members->node_items + i; + int size = type_sizeof(member->ty); + int align = type_alignof(member->ty); + + size = to_aligned(size, align); + if (union_size < size) { + union_size = size; + } + if (union_align < align) { + union_align = align; + } + } + return to_aligned(union_size, union_align); +} + +int type_alignof_struct(Type* ty) { + int struct_align = 0; + + for (int i = 0; i < ty->def->node_members->node_len; ++i) { + AstNode* member = ty->def->node_members->node_items + i; + int align = type_alignof(member->ty); + + if (struct_align < align) { + struct_align = align; + } + } + return struct_align; +} + +int type_alignof_union(Type* ty) { + int union_align = 0; + + for (int i = 0; i < ty->def->node_members->node_len; ++i) { + AstNode* member = ty->def->node_members->node_items + i; + int align = type_alignof(member->ty); + + if (union_align < align) { + union_align = align; + } + } + return union_align; +} + +int type_offsetof(Type* ty, const char* name) { + if (ty->kind == TypeKind_union) { + return 0; + } + if (ty->kind != TypeKind_struct) { + fatal_error("type_offsetof: type is neither a struct nor a union"); + } + + int next_offset = 0; + + for (int i = 0; i < ty->def->node_members->node_len; ++i) { + AstNode* member = ty->def->node_members->node_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) { + return next_offset; + } + next_offset += size; + } + + fatal_error("type_offsetof: member not found"); +} + +Type* type_member_typeof(Type* ty, const char* name) { + if (ty->kind != TypeKind_struct && ty->kind != TypeKind_union) { + fatal_error("type_member_typeof: type is neither a struct nor a union"); + } + + for (int i = 0; i < ty->def->node_members->node_len; ++i) { + AstNode* member = ty->def->node_members->node_items + i; + if (strcmp(member->name, name) == 0) { + return member->ty; + } + } + + fatal_error("type_offsetof: member not found"); +} |
