diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-07-29 19:40:40 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-08-15 10:04:40 +0900 |
| commit | 3df0d758471d7654d4b85ef15a1675b4d62e7c41 (patch) | |
| tree | 48d6a1abceb5566779cfeddb8b9f1d7148ea2ea8 | |
| parent | 144875f4687e8cfa77f8b1b7e5ff8790f8f5b684 (diff) | |
| download | ducc-3df0d758471d7654d4b85ef15a1675b4d62e7c41.tar.gz ducc-3df0d758471d7654d4b85ef15a1675b4d62e7c41.tar.zst ducc-3df0d758471d7654d4b85ef15a1675b4d62e7c41.zip | |
feat: implement array type
| -rw-r--r-- | ast.c | 30 | ||||
| -rw-r--r-- | codegen.c | 4 | ||||
| -rw-r--r-- | parse.c | 11 | ||||
| -rw-r--r-- | tests/068.sh | 29 |
4 files changed, 71 insertions, 3 deletions
@@ -6,6 +6,7 @@ enum TypeKind { TypeKind_long, TypeKind_void, TypeKind_ptr, + TypeKind_array, TypeKind_enum, TypeKind_struct, }; @@ -16,6 +17,7 @@ struct AstNode; struct Type { TypeKind kind; struct Type* to; + int array_size; struct AstNode* def; }; typedef struct Type Type; @@ -33,6 +35,18 @@ Type* type_new_ptr(Type* to) { return ty; } +Type* type_new_array(Type* elem, int size) { + Type* ty = calloc(1, sizeof(Type)); + ty->kind = TypeKind_array; + ty->to = elem; + ty->array_size = size; + return ty; +} + +Type* type_array_to_ptr(Type* ty) { + return type_new_ptr(ty->to); +} + int type_is_unsized(Type* ty) { return ty->kind != TypeKind_void; } @@ -57,6 +71,8 @@ int type_sizeof(Type* ty) { return 8; } else if (ty->kind == TypeKind_enum) { return 4; + } else if (ty->kind == TypeKind_array) { + return type_sizeof(ty->to) * ty->array_size; } else { return type_sizeof_struct(ty); } @@ -77,6 +93,8 @@ int type_alignof(Type* ty) { return 8; } else if (ty->kind == TypeKind_enum) { return 4; + } else if (ty->kind == TypeKind_array) { + return type_alignof(ty->to); } else { return type_alignof_struct(ty); } @@ -209,14 +227,20 @@ AstNode* ast_new_binary_expr(int op, AstNode* lhs, AstNode* 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); } @@ -236,16 +260,16 @@ AstNode* ast_new_assign_expr(int op, AstNode* lhs, AstNode* rhs) { } AstNode* ast_new_assign_add_expr(AstNode* lhs, AstNode* rhs) { - if (lhs->ty->kind == TypeKind_ptr) { + if (lhs->ty->kind == TypeKind_ptr || lhs->ty->kind == TypeKind_array) { rhs = ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->to))); - } else if (rhs->ty->kind == TypeKind_ptr) { + } else if (rhs->ty->kind == TypeKind_ptr || rhs->ty->kind == TypeKind_array) { lhs = ast_new_binary_expr(TokenKind_star, lhs, ast_new_int(type_sizeof(rhs->ty->to))); } return ast_new_assign_expr(TokenKind_assign_add, lhs, rhs); } AstNode* ast_new_assign_sub_expr(AstNode* lhs, AstNode* rhs) { - if (lhs->ty->kind == TypeKind_ptr) { + if (lhs->ty->kind == TypeKind_ptr || lhs->ty->kind == TypeKind_array) { rhs = ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->to))); } return ast_new_assign_expr(TokenKind_assign_sub, lhs, rhs); @@ -88,6 +88,10 @@ void codegen_ref_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { } void codegen_lval2rval(Type* ty) { + if (ty->kind == TypeKind_array) { + return; + } + int size = type_sizeof(ty); printf(" pop rax\n"); @@ -702,6 +702,17 @@ AstNode* parse_var_decl(Parser* p) { } String* name = parse_ident(p); + if (peek_token(p)->kind == TokenKind_bracket_l) { + next_token(p); + AstNode* size_expr = parse_expr(p); + if (size_expr->kind != AstNodeKind_int_expr) { + fatal_error("parse_var_decl: invalid array size"); + } + int size = size_expr->node_int_value; + expect(p, TokenKind_bracket_r); + ty = type_new_array(ty, size); + } + AstNode* init = NULL; if (peek_token(p)->kind == TokenKind_assign) { next_token(p); diff --git a/tests/068.sh b/tests/068.sh new file mode 100644 index 0000000..648e822 --- /dev/null +++ b/tests/068.sh @@ -0,0 +1,29 @@ +set -e + +cat <<'EOF' > expected +0 +1 +4 +9 +16 +25 +36 +49 +64 +81 +EOF + +bash ../../test_diff.sh <<'EOF' +int printf(); + +int main() { + int i; + int a[10]; + for (i = 0; i < 10; ++i) { + a[i] = i * i; + } + for (i = 0; i < 10; ++i) { + printf("%d\n", a[i]); + } +} +EOF |
