diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-09-27 08:28:37 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-09-27 09:07:20 +0900 |
| commit | 1c270ba5e27f126a251b5591cfac4243ba3c75f7 (patch) | |
| tree | 8d13499752aefeb598d8a51ce22975d0031296db /src | |
| parent | edb1612b9f5d5485528e24470b88a7d602772ad6 (diff) | |
| download | ducc-1c270ba5e27f126a251b5591cfac4243ba3c75f7.tar.gz ducc-1c270ba5e27f126a251b5591cfac4243ba3c75f7.tar.zst ducc-1c270ba5e27f126a251b5591cfac4243ba3c75f7.zip | |
feat: allow variable initializer to access previously declared variables
Diffstat (limited to 'src')
| -rw-r--r-- | src/parse.c | 85 |
1 files changed, 42 insertions, 43 deletions
diff --git a/src/parse.c b/src/parse.c index e9e9312..21d399b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1118,6 +1118,8 @@ static AstNode* parse_init_declarator(Parser* p, Type* ty) { return decl; } +static void declare_func_or_var(Parser* p, AstNode* decl); + // init-declarator-list: // init-declarator // init-declarator-list ',' init-declarator @@ -1129,40 +1131,22 @@ static AstNode* parse_init_declarator_list(Parser* p, Type* ty) { if (!consume_token_if(p, TokenKind_comma)) { break; } + + if (ty->storage_class == StorageClass_typedef) { + continue; + } + // 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]); } return list; } static AstNode* parse_var_decl(Parser* p) { Type* base_ty = parse_type_name(p); - if (type_is_unsized(base_ty)) { - fatal_error("parse_var_decl: invalid type for variable"); - } - AstNode* decls = parse_init_declarator_list(p, base_ty); expect(p, TokenKind_semicolon); - - for (int i = 0; i < decls->node_len; ++i) { - AstNode* decl = &decls->node_items[i]; - - if (find_lvar_in_current_scope(p, decl->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); - } - int stack_offset = add_lvar(p, decl->name, decl->ty, false); - - 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); - decl->kind = AstNodeKind_expr_stmt; - decl->node_expr = assign; - } else { - decl->kind = AstNodeKind_nop; - } - } + declare_func_or_var(p, &decls->node_items[decls->node_len - 1]); return decls; } @@ -1310,24 +1294,39 @@ static void register_func(Parser* p, const char* name, Type* ty) { func->ty = ty; } -static AstNode* parse_global_func_or_var_decl(Parser* p, AstNode* decls) { - expect(p, TokenKind_semicolon); - - for (int i = 0; i < decls->node_len; ++i) { - AstNode* decl = &decls->node_items[i]; +static void declare_func_or_var(Parser* p, AstNode* decl) { + 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); + decl->kind = AstNodeKind_func_decl; + } else { + if (type_is_unsized(decl->ty)) { + fatal_error("declare_func_or_var: invalid type for variable"); + } - if (decl->ty->kind == TypeKind_func) { - if (decls->node_len != 1) { - fatal_error("parse_global_func_or_var_decl: todo"); + if (p->scope) { + if (find_lvar_in_current_scope(p, decl->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); + } + int stack_offset = add_lvar(p, decl->name, decl->ty, false); + + 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); + decl->kind = AstNodeKind_expr_stmt; + decl->node_expr = assign; + } else { + decl->kind = AstNodeKind_nop; } - // 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); - decl->kind = AstNodeKind_func_decl; } else { if (find_gvar(p, decl->name) != -1) { - fatal_error("parse_global_func_or_var_decl: %s redeclared", decl->name); + fatal_error("declare_func_or_var: %s redeclared", decl->name); } // TODO: refactor Type* base_ty = decl->ty; @@ -1349,8 +1348,6 @@ static AstNode* parse_global_func_or_var_decl(Parser* p, AstNode* decls) { } } } - - return decls; } static AstNode* parse_func_def(Parser* p, AstNode* decls) { @@ -2245,7 +2242,9 @@ static AstNode* parse_toplevel(Parser* p) { parse_typedef_decl(p, decls); return NULL; } else { - return parse_global_func_or_var_decl(p, decls); + expect(p, TokenKind_semicolon); + declare_func_or_var(p, &decls->node_items[decls->node_len - 1]); + return decls; } } |
