From 745c325d0f498406f229e532753e5d5712e824d4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 May 2016 12:34:03 -0700 Subject: [PATCH] support variable declarations in structs See #22 --- doc/langref.md | 2 +- src/all_types.hpp | 2 +- src/analyze.cpp | 6 +++--- src/parser.cpp | 15 +++++++++++---- test/self_hosted.zig | 8 ++++++++ 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index ddadcb6c5e..d43feb27c3 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -17,7 +17,7 @@ VariableDeclaration = ("var" | "const") "Symbol" option(":" TypeExpr) "=" Expres ContainerDecl = ("struct" | "enum" | "union") "Symbol" option(ParamDeclList) "{" many(StructMember) "}" -StructMember = many(Directive) option(VisibleMod) (StructField | FnDef) +StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl) StructField = "Symbol" option(":" Expression) ",") diff --git a/src/all_types.hpp b/src/all_types.hpp index f6342cb8a0..b44bbb7e6d 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -604,7 +604,7 @@ struct AstNodeStructDecl { ZigList generic_params; bool generic_params_is_var_args; // always an error but it can happen from parsing ZigList fields; - ZigList fns; + ZigList decls; // populated by semantic analyzer BlockContext *block_context; diff --git a/src/analyze.cpp b/src/analyze.cpp index 233bc4e7b2..ac26cb3980 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1580,8 +1580,8 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, BlockContext node->data.struct_decl.type_entry = container_type; // handle the member function definitions independently - for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { - AstNode *child_node = node->data.struct_decl.fns.at(i); + for (int i = 0; i < node->data.struct_decl.decls.length; i += 1) { + AstNode *child_node = node->data.struct_decl.decls.at(i); get_as_top_level_decl(child_node)->parent_decl = node; BlockContext *child_context = get_container_block_context(container_type); scan_decls(g, import, child_context, child_node); @@ -1669,7 +1669,7 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) case NodeTypeVariableDeclaration: { AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; - VariableTableEntry *var = analyze_variable_declaration_raw(g, import, import->block_context, + VariableTableEntry *var = analyze_variable_declaration_raw(g, import, node->block_context, node, variable_declaration, false, node, false); g->global_vars.append(var); diff --git a/src/parser.cpp b/src/parser.cpp index bef763f500..9a85dc3b9e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2605,7 +2605,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index, /* ContainerDecl = ("struct" | "enum" | "union") "Symbol" option(ParamDeclList) "{" many(StructMember) "}" -StructMember: many(Directive) option(VisibleMod) (StructField | FnDef) +StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl) StructField : "Symbol" option(":" Expression) ",") */ static AstNode *ast_parse_container_decl(ParseContext *pc, int *token_index, @@ -2664,7 +2664,14 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, int *token_index, AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directive_list, visib_mod); if (fn_def_node) { - node->data.struct_decl.fns.append(fn_def_node); + node->data.struct_decl.decls.append(fn_def_node); + continue; + } + + AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, directive_list, visib_mod); + if (var_decl_node) { + ast_eat_token(pc, token_index, TokenIdSemicolon); + node->data.struct_decl.decls.append(var_decl_node); continue; } @@ -3035,7 +3042,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont break; case NodeTypeStructDecl: visit_node_list(&node->data.struct_decl.fields, visit, context); - visit_node_list(&node->data.struct_decl.fns, visit, context); + visit_node_list(&node->data.struct_decl.decls, visit, context); visit_node_list(node->data.struct_decl.top_level_decl.directives, visit, context); break; case NodeTypeStructField: @@ -3278,7 +3285,7 @@ AstNode *ast_clone_subtree(AstNode *old_node, uint32_t *next_node_index) { case NodeTypeStructDecl: clone_subtree_list(&new_node->data.struct_decl.fields, &old_node->data.struct_decl.fields, next_node_index); - clone_subtree_list(&new_node->data.struct_decl.fns, &old_node->data.struct_decl.fns, + clone_subtree_list(&new_node->data.struct_decl.decls, &old_node->data.struct_decl.decls, next_node_index); clone_subtree_list_ptr(&new_node->data.struct_decl.top_level_decl.directives, old_node->data.struct_decl.top_level_decl.directives, next_node_index); diff --git a/test/self_hosted.zig b/test/self_hosted.zig index ab5fde33a9..2c1b462334 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -1640,3 +1640,11 @@ fn truncate() { fn test_truncate(x: u32) -> u8 { @truncate(u8, x) } + +#attribute("test") +fn const_decls_in_struct() { + assert(GenericDataThing(3).count_plus_one == 4); +} +struct GenericDataThing(count: isize) { + const count_plus_one = count + 1; +}