diff options
| -rw-r--r-- | src/parse.c | 85 | ||||
| -rw-r--r-- | tests/test_local_variables.sh | 14 |
2 files changed, 48 insertions, 51 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; } } diff --git a/tests/test_local_variables.sh b/tests/test_local_variables.sh index dfa704b..674899d 100644 --- a/tests/test_local_variables.sh +++ b/tests/test_local_variables.sh @@ -44,15 +44,13 @@ int main() { } EOF -cat <<'EOF' > expected -42 -EOF -test_diff <<'EOF' -int printf(); +test_exit_code 0 <<'EOF' +#include "../../helpers.h" int main() { - int a = 42; - printf("%d\n", a); - return 0; + int d = 2, e = d, f = d + e; + ASSERT_EQ(2, d); + ASSERT_EQ(2, e); + ASSERT_EQ(4, f); } EOF |
