Commit 9375ad0d3b

Andrew Kelley <andrew@ziglang.org>
2021-04-17 02:57:51
AstGen: implement global var decls
And fix bug with using `ensureCapacity` when I wanted `ensureUnusedCapacity`.
1 parent c8ae581
Changed files (3)
src/AstGen.zig
@@ -1281,6 +1281,7 @@ fn blockExprStmts(
                         .bit_or,
                         .block,
                         .block_inline,
+                        .block_inline_var,
                         .loop,
                         .bool_br_and,
                         .bool_br_or,
@@ -2020,7 +2021,7 @@ fn fnDecl(
         // Iterate over the parameters. We put the param names as the first N
         // items inside `extra` so that debug info later can refer to the parameter names
         // even while the respective source code is unloaded.
-        try astgen.extra.ensureCapacity(gpa, param_count);
+        try astgen.extra.ensureUnusedCapacity(gpa, param_count);
 
         {
             var params_scope = &fn_gz.base;
@@ -2080,7 +2081,7 @@ fn fnDecl(
     };
 
     const fn_name_token = fn_proto.name_token orelse {
-        @panic("TODO handle missing function names in the parser");
+        return astgen.failTok(fn_proto.ast.fn_token, "missing function name", .{});
     };
     const fn_name_str_index = try gz.identAsString(fn_name_token);
 
@@ -2173,16 +2174,13 @@ fn globalVarDecl(
             var_decl.ast.init_node,
         );
 
-        if (!is_mutable) {
-            // const globals are just their instruction. mutable globals have
-            // a special ZIR form.
-            const block_inst = try gz.addBlock(.block_inline, node);
-            _ = try block_scope.addBreak(.break_inline, block_inst, init_inst);
-            try block_scope.setBlockBody(block_inst);
-            break :vi block_inst;
-        }
-
-        @panic("TODO astgen global variable");
+        const tag: Zir.Inst.Tag = if (is_mutable) .block_inline_var else .block_inline;
+        // const globals are just their instruction. mutable globals have
+        // a special ZIR form.
+        const block_inst = try gz.addBlock(tag, node);
+        _ = try block_scope.addBreak(.break_inline, block_inst, init_inst);
+        try block_scope.setBlockBody(block_inst);
+        break :vi block_inst;
     } else if (!is_extern) {
         return astgen.failNode(node, "variables must be initialized", .{});
     } else if (var_decl.ast.type_node != 0) {
@@ -2190,7 +2188,7 @@ fn globalVarDecl(
 
         const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
 
-        @panic("TODO AstGen extern global variable");
+        return astgen.failNode(node, "TODO AstGen extern global variable", .{});
     } else {
         return astgen.failNode(node, "unable to infer variable type", .{});
     };
@@ -2588,7 +2586,7 @@ fn containerDecl(
                 );
             }
             if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) {
-                @panic("AstGen simple enum");
+                return astgen.failNode(node, "TODO AstGen simple enums", .{});
             }
             // In this case we must generate ZIR code for the tag values, similar to
             // how structs are handled above.
@@ -2698,7 +2696,7 @@ fn errorSetDecl(
     const main_tokens = tree.nodes.items(.main_token);
     const token_tags = tree.tokens.items(.tag);
 
-    @panic("TODO AstGen errorSetDecl");
+    return astgen.failNode(node, "TODO AstGen errorSetDecl", .{});
 }
 
 fn orelseCatchExpr(
src/Sema.zig
@@ -367,7 +367,7 @@ pub fn analyzeBody(
                 i = 0;
                 continue;
             },
-            .block_inline => blk: {
+            .block_inline, .block_inline_var => blk: {
                 // Directly analyze the block body without introducing a new block.
                 const inst_data = datas[inst].pl_node;
                 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
src/Zir.zig
@@ -208,6 +208,8 @@ pub const Inst = struct {
         /// a noreturn instruction.
         /// Uses the `pl_node` union field. Payload is `Block`.
         block_inline,
+        /// Same as `block_inline` but it additionally marks a decl as being a variable.
+        block_inline_var,
         /// Boolean AND. See also `bit_and`.
         /// Uses the `pl_node` union field. Payload is `Bin`.
         bool_and,
@@ -753,6 +755,7 @@ pub const Inst = struct {
                 .bit_or,
                 .block,
                 .block_inline,
+                .block_inline_var,
                 .loop,
                 .bool_br_and,
                 .bool_br_or,
@@ -1830,6 +1833,7 @@ const Writer = struct {
 
             .block,
             .block_inline,
+            .block_inline_var,
             .loop,
             .validate_struct_init_ptr,
             => try self.writePlNodeBlock(stream, inst),