diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-08-11 12:44:40 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-08-15 10:06:21 +0900 |
| commit | fc55b5f89b5974f627657c730bfd6b7d01609eae (patch) | |
| tree | b594b55bc00a71a0fb83b8e15bf959c1dfdeeb6f | |
| parent | cf38ecdd3611efe138e24ea6b5b91c1861f36f31 (diff) | |
| download | ducc-fc55b5f89b5974f627657c730bfd6b7d01609eae.tar.gz ducc-fc55b5f89b5974f627657c730bfd6b7d01609eae.tar.zst ducc-fc55b5f89b5974f627657c730bfd6b7d01609eae.zip | |
feat: allow variable declaration in for loop's init
| -rw-r--r-- | ast.c | 18 | ||||
| -rw-r--r-- | codegen.c | 17 | ||||
| -rw-r--r-- | parse.c | 137 | ||||
| -rw-r--r-- | preprocess.c | 12 | ||||
| -rw-r--r-- | tests/087.sh | 24 |
5 files changed, 107 insertions, 101 deletions
@@ -357,8 +357,7 @@ int type_sizeof_struct(Type* ty) { int next_offset = 0; int struct_align = 0; - int i; - for (i = 0; i < ty->def->node_members->node_len; ++i) { + 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); @@ -376,8 +375,7 @@ int type_sizeof_union(Type* ty) { int union_size = 0; int union_align = 0; - int i; - for (i = 0; i < ty->def->node_members->node_len; ++i) { + 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); @@ -396,8 +394,7 @@ int type_sizeof_union(Type* ty) { int type_alignof_struct(Type* ty) { int struct_align = 0; - int i; - for (i = 0; i < ty->def->node_members->node_len; ++i) { + 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); @@ -411,8 +408,7 @@ int type_alignof_struct(Type* ty) { int type_alignof_union(Type* ty) { int union_align = 0; - int i; - for (i = 0; i < ty->def->node_members->node_len; ++i) { + 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); @@ -433,8 +429,7 @@ int type_offsetof(Type* ty, const String* name) { int next_offset = 0; - int i; - for (i = 0; i < ty->def->node_members->node_len; ++i) { + 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); @@ -454,8 +449,7 @@ Type* type_member_typeof(Type* ty, const String* name) { fatal_error("type_member_typeof: type is neither a struct nor a union"); } - int i; - for (i = 0; i < ty->def->node_members->node_len; ++i) { + for (int i = 0; i < ty->def->node_members->node_len; ++i) { AstNode* member = ty->def->node_members->node_items + i; if (string_equals(&member->name, name)) { return member->ty; @@ -47,8 +47,7 @@ const char* param_reg(int n) { void codegen_func_prologue(CodeGen* g, AstNode* ast) { printf(" push rbp\n"); printf(" mov rbp, rsp\n"); - int i; - for (i = 0; i < ast->node_params->node_len; ++i) { + for (int i = 0; i < ast->node_params->node_len; ++i) { printf(" push %s\n", param_reg(i)); } printf(" sub rsp, %d\n", 8 * LVAR_MAX); @@ -105,8 +104,7 @@ void codegen_push_expr(const char* reg, int size) { // Perform bitwise copy. Use r10 register as temporary space. // Note: rsp must be aligned to 8. printf(" sub rsp, %d\n", to_aligned(size, 8)); - int i; - for (i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { // Copy a sinle byte from the address that "reg" points to to the stack via r10 register. printf(" mov r10b, [%s+%d]\n", reg, i); printf(" mov [rsp+%d], r10b\n", i); @@ -250,8 +248,7 @@ void codegen_assign_expr(CodeGen* g, AstNode* ast) { int aligned_size = to_aligned(sizeof_lhs, 8); printf(" mov rax, [rsp+%d]\n", aligned_size); // Perform bitwise copy. Use r10 register as temporary space. - int i; - for (i = 0; i < aligned_size; ++i) { + for (int i = 0; i < aligned_size; ++i) { // Copy a sinle byte from the stack to the address that rax points to via r10 register. printf(" mov r10b, [rsp+%d]\n", i); printf(" mov [rax+%d], r10b\n", i); @@ -340,8 +337,7 @@ void codegen_gvar(CodeGen* g, AstNode* ast, GenMode gen_mode) { void codegen_composite_expr(CodeGen* g, AstNode* ast) { // Standard C does not have composite expression, but ducc internally has. - int i; - for (i = 0; i < ast->node_len; ++i) { + for (int i = 0; i < ast->node_len; ++i) { AstNode* expr = ast->node_items + i; codegen_expr(g, expr, GenMode_rval); if (i != ast->node_len - 1) { @@ -472,8 +468,7 @@ void codegen_nop(CodeGen* g, AstNode* ast) { } void codegen_block_stmt(CodeGen* g, AstNode* ast) { - int i; - for (i = 0; i < ast->node_len; ++i) { + for (int i = 0; i < ast->node_len; ++i) { AstNode* stmt = ast->node_items + i; codegen_stmt(g, stmt); } @@ -521,11 +516,11 @@ void codegen_func(CodeGen* g, AstNode* ast) { void codegen(Program* prog) { CodeGen* g = codegen_new(); + int i; printf(".intel_syntax noprefix\n\n"); printf(".section .rodata\n\n"); - int i; for (i = 0; prog->str_literals[i]; ++i) { printf(".Lstr__%d:\n", i + 1); printf(" .string \"%s\"\n\n", prog->str_literals[i]); @@ -84,8 +84,7 @@ Token* expect(Parser* p, TokenKind expected) { } int find_lvar(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_lvars; ++i) { + for (int i = 0; i < p->n_lvars; ++i) { if (string_equals(&p->lvars[i].name, name)) { return i; } @@ -127,8 +126,7 @@ int add_lvar(Parser* p, String* name, Type* ty, BOOL is_param) { String* generate_temporary_lvar_name(Parser* p) { String* ret = calloc(1, sizeof(String)); ret->data = calloc(256, sizeof(char)); - int i; - for (i = 1;; ++i) { + for (int i = 1;; ++i) { ret->len = sprintf(ret->data, "__%d", i); if (find_lvar(p, ret) == -1) { return ret; @@ -147,8 +145,7 @@ AstNode* generate_temporary_lvar(Parser* p, Type* ty) { } int find_gvar(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_gvars; ++i) { + for (int i = 0; i < p->n_gvars; ++i) { if (string_equals(&p->gvars[i].name, name)) { return i; } @@ -157,8 +154,7 @@ int find_gvar(Parser* p, const String* name) { } int find_func(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_funcs; ++i) { + for (int i = 0; i < p->n_funcs; ++i) { if (string_equals(&p->funcs[i].name, name)) { return i; } @@ -167,8 +163,7 @@ int find_func(Parser* p, const String* name) { } int find_struct(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_structs; ++i) { + for (int i = 0; i < p->n_structs; ++i) { if (string_equals(&p->structs[i].name, name)) { return i; } @@ -177,8 +172,7 @@ int find_struct(Parser* p, const String* name) { } int find_union(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_unions; ++i) { + for (int i = 0; i < p->n_unions; ++i) { if (string_equals(&p->unions[i].name, name)) { return i; } @@ -187,8 +181,7 @@ int find_union(Parser* p, const String* name) { } int find_enum(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_enums; ++i) { + for (int i = 0; i < p->n_enums; ++i) { if (string_equals(&p->enums[i].name, name)) { return i; } @@ -197,10 +190,8 @@ int find_enum(Parser* p, const String* name) { } int find_enum_member(Parser* p, const String* name) { - int i; - int j; - for (i = 0; i < p->n_enums; ++i) { - for (j = 0; j < p->enums[i].node_members->node_len; ++j) { + for (int i = 0; i < p->n_enums; ++i) { + for (int j = 0; j < p->enums[i].node_members->node_len; ++j) { if (string_equals(&p->enums[i].node_members->node_items[j].name, name)) { return i * 1000 + j; } @@ -210,8 +201,7 @@ int find_enum_member(Parser* p, const String* name) { } int find_typedef(Parser* p, const String* name) { - int i; - for (i = 0; i < p->n_typedefs; ++i) { + for (int i = 0; i < p->n_typedefs; ++i) { if (string_equals(&p->typedefs[i].name, name)) { return i; } @@ -287,7 +277,7 @@ AstNode* parse_primary_expr(Parser* p) { e->ty = p->lvars[lvar_idx].ty; return e; } else { - fatal_error("expected primary expression, but got '%s'", token_stringify(t)); + fatal_error("%s:%d: expected an expression, but got '%s'", t->loc.filename, t->loc.line, token_stringify(t)); } } @@ -718,6 +708,53 @@ AstNode* parse_if_stmt(Parser* p) { return stmt; } +AstNode* parse_var_decl(Parser* p) { + Type* ty = parse_type(p); + if (type_is_unsized(ty)) { + fatal_error("parse_var_decl: invalid type for variable"); + } + 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); + init = parse_expr(p); + } + expect(p, TokenKind_semicolon); + + if (find_lvar(p, name) != -1 || find_gvar(p, name) != -1) { + // TODO: use name's location. + fatal_error("%s:%d: parse_var_decl: %.*s redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, + name->len, name->data); + } + int stack_offset = add_lvar(p, name, ty, FALSE); + + AstNode* ret; + if (init) { + AstNode* lhs = ast_new(AstNodeKind_lvar); + lhs->name = *name; + lhs->node_stack_offset = stack_offset; + lhs->ty = ty; + AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, init); + ret = ast_new(AstNodeKind_expr_stmt); + ret->node_expr = assign; + } else { + ret = ast_new(AstNodeKind_lvar_decl); + } + return ret; +} + AstNode* parse_for_stmt(Parser* p) { expect(p, TokenKind_keyword_for); expect(p, TokenKind_paren_l); @@ -725,9 +762,15 @@ AstNode* parse_for_stmt(Parser* p) { AstNode* cond = NULL; AstNode* update = NULL; if (peek_token(p)->kind != TokenKind_semicolon) { - init = parse_expr(p); + if (is_type_token(p, peek_token(p))) { + init = parse_var_decl(p)->node_expr; + } else { + init = parse_expr(p); + expect(p, TokenKind_semicolon); + } + } else { + expect(p, TokenKind_semicolon); } - expect(p, TokenKind_semicolon); if (peek_token(p)->kind != TokenKind_semicolon) { cond = parse_expr(p); } else { @@ -788,51 +831,6 @@ AstNode* parse_continue_stmt(Parser* p) { return ast_new(AstNodeKind_continue_stmt); } -AstNode* parse_var_decl(Parser* p) { - Type* ty = parse_type(p); - if (type_is_unsized(ty)) { - fatal_error("parse_var_decl: invalid type for variable"); - } - 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); - init = parse_expr(p); - } - expect(p, TokenKind_semicolon); - - if (find_lvar(p, name) != -1 || find_gvar(p, name) != -1) { - fatal_error("parse_var_decl: %.*s redeclared", name->len, name->data); - } - int stack_offset = add_lvar(p, name, ty, FALSE); - - AstNode* ret; - if (init) { - AstNode* lhs = ast_new(AstNodeKind_lvar); - lhs->name = *name; - lhs->node_stack_offset = stack_offset; - lhs->ty = ty; - AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, init); - ret = ast_new(AstNodeKind_expr_stmt); - ret->node_expr = assign; - } else { - ret = ast_new(AstNodeKind_lvar_decl); - } - return ret; -} - AstNode* parse_expr_stmt(Parser* p) { AstNode* e = parse_expr(p); expect(p, TokenKind_semicolon); @@ -890,8 +888,7 @@ void enter_func(Parser* p) { } void register_params(Parser* p, AstNode* params) { - int i; - for (i = 0; i < params->node_len; ++i) { + for (int i = 0; i < params->node_len; ++i) { AstNode* param = params->node_items + i; add_lvar(p, ¶m->name, param->ty, TRUE); } diff --git a/preprocess.c b/preprocess.c index 7ba7c7c..b7e52bf 100644 --- a/preprocess.c +++ b/preprocess.c @@ -336,11 +336,10 @@ PpMacros* pp_macros_new() { } void pp_macros_dump(PpMacros* pp_macros) { - int i; fprintf(stderr, "PpMacros {\n"); fprintf(stderr, " len = %zu\n", pp_macros->len); fprintf(stderr, " data = [\n"); - for (i = 0; i < pp_macros->len; ++i) { + for (int i = 0; i < pp_macros->len; ++i) { PpMacro* m = &pp_macros->data[i]; fprintf(stderr, " PpMacro {\n"); fprintf(stderr, " kind = %s\n", pp_macro_kind_stringify(m->kind)); @@ -406,8 +405,7 @@ Preprocessor* preprocessor_new(InFile* src, int include_depth, PpMacros* pp_macr } int find_pp_macro(Preprocessor* pp, String* name) { - int i; - for (i = 0; i < pp->pp_macros->len; ++i) { + for (int i = 0; i < pp->pp_macros->len; ++i) { if (string_equals(&pp->pp_macros->data[i].name, name)) { return i; } @@ -722,8 +720,7 @@ Token* skip_whitespace(Token* tok) { } BOOL string_contains_newline(String* s) { - int i; - for (i = 0; i < s->len; ++i) { + for (int i = 0; i < s->len; ++i) { if (s->data[i] == '\n') { return TRUE; } @@ -834,8 +831,7 @@ const char* resolve_include_name(Preprocessor* pp, String* include_name) { sprintf(buf, "%.*s", include_name->len - 2, include_name->data + 1); return buf; } else { - int i; - for (i = 0; i < pp->n_include_paths; ++i) { + for (int i = 0; i < pp->n_include_paths; ++i) { buf = calloc(include_name->len + 1 + pp->include_paths[i].len, sizeof(char)); sprintf(buf, "%s/%.*s", pp->include_paths[i].data, include_name->len, include_name->data); if (access(buf, F_OK | R_OK) == 0) { diff --git a/tests/087.sh b/tests/087.sh new file mode 100644 index 0000000..e662687 --- /dev/null +++ b/tests/087.sh @@ -0,0 +1,24 @@ +set -e + +cat <<'EOF' > expected +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +EOF + +bash ../../test_diff.sh <<'EOF' +int printf(); + +int main() { + for (int i = 0; i < 10; i++) { + printf("%d\n", i); + } +} +EOF |
