Commit 8111453cc1

Isaac Freund <ifreund@ifreund.xyz>
2021-03-22 14:54:13
astgen: implement array types
1 parent 4f3071a
Changed files (4)
lib/std/zig/ast.zig
@@ -1430,7 +1430,7 @@ pub const Tree = struct {
             .ast = .{
                 .lbracket = tree.nodes.items(.main_token)[node],
                 .elem_count = data.lhs,
-                .sentinel = null,
+                .sentinel = 0,
                 .elem_type = data.rhs,
             },
         };
@@ -1440,6 +1440,7 @@ pub const Tree = struct {
         assert(tree.nodes.items(.tag)[node] == .array_type_sentinel);
         const data = tree.nodes.items(.data)[node];
         const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel);
+        assert(extra.sentinel != 0);
         return .{
             .ast = .{
                 .lbracket = tree.nodes.items(.main_token)[node],
@@ -2262,7 +2263,7 @@ pub const full = struct {
         pub const Ast = struct {
             lbracket: TokenIndex,
             elem_count: Node.Index,
-            sentinel: ?Node.Index,
+            sentinel: Node.Index,
             elem_type: Node.Index,
         };
     };
@@ -2549,9 +2550,9 @@ pub const Node = struct {
         @"await",
         /// `?lhs`. rhs unused. main_token is the `?`.
         optional_type,
-        /// `[lhs]rhs`. lhs can be omitted to make it a slice.
+        /// `[lhs]rhs`.
         array_type,
-        /// `[lhs:a]b`. `array_type_sentinel[rhs]`.
+        /// `[lhs:a]b`. `ArrayTypeSentinel[rhs]`.
         array_type_sentinel,
         /// `[*]align(lhs) rhs`. lhs can be omitted.
         /// `*align(lhs) rhs`. lhs can be omitted.
lib/std/zig/render.zig
@@ -717,9 +717,9 @@ fn renderArrayType(
     ais.pushIndentNextLine();
     try renderToken(ais, tree, array_type.ast.lbracket, inner_space); // lbracket
     try renderExpression(gpa, ais, tree, array_type.ast.elem_count, inner_space);
-    if (array_type.ast.sentinel) |sentinel| {
-        try renderToken(ais, tree, tree.firstToken(sentinel) - 1, inner_space); // colon
-        try renderExpression(gpa, ais, tree, sentinel, inner_space);
+    if (array_type.ast.sentinel != 0) {
+        try renderToken(ais, tree, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon
+        try renderExpression(gpa, ais, tree, array_type.ast.sentinel, inner_space);
     }
     ais.popIndent();
     try renderToken(ais, tree, rbracket, .none); // rbracket
src/astgen.zig
@@ -1390,56 +1390,33 @@ fn ptrType(
 }
 
 fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {
-    if (true) @panic("TODO update for zir-memory-layout");
     const tree = scope.tree();
-    const main_tokens = tree.nodes.items(.main_token);
     const node_datas = tree.nodes.items(.data);
+    const gz = scope.getGenZir();
+    const usize_type = @enumToInt(zir.Const.usize_type);
 
-    const usize_type = try addZIRInstConst(mod, scope, src, .{
-        .ty = Type.initTag(.type),
-        .val = Value.initTag(.usize_type),
-    });
-    const len_node = node_datas[node].lhs;
-    const elem_node = node_datas[node].rhs;
-    if (len_node == 0) {
-        const elem_type = try typeExpr(mod, scope, elem_node);
-        const result = try addZIRUnOp(mod, scope, src, .mut_slice_type, elem_type);
-        return rvalue(mod, scope, rl, result);
-    } else {
-        // TODO check for [_]T
-        const len = try expr(mod, scope, .{ .ty = usize_type }, len_node);
-        const elem_type = try typeExpr(mod, scope, elem_node);
+    // TODO check for [_]T
+    const len = try expr(mod, scope, .{ .ty = usize_type }, node_datas[node].lhs);
+    const elem_type = try typeExpr(mod, scope, node_datas[node].rhs);
 
-        const result = try addZIRBinOp(mod, scope, src, .array_type, len, elem_type);
-        return rvalue(mod, scope, rl, result);
-    }
+    const result = try gz.addBin(.array_type, len, elem_type);
+    return rvalue(mod, scope, rl, result, node);
 }
 
 fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {
-    if (true) @panic("TODO update for zir-memory-layout");
     const tree = scope.tree();
-    const main_tokens = tree.nodes.items(.main_token);
     const node_datas = tree.nodes.items(.data);
-
-    const len_node = node_datas[node].lhs;
     const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);
-    const usize_type = try addZIRInstConst(mod, scope, src, .{
-        .ty = Type.initTag(.type),
-        .val = Value.initTag(.usize_type),
-    });
+    const gz = scope.getGenZir();
+    const usize_type = @enumToInt(zir.Const.usize_type);
 
     // TODO check for [_]T
-    const len = try expr(mod, scope, .{ .ty = usize_type }, len_node);
-    const sentinel_uncasted = try expr(mod, scope, .none, extra.sentinel);
+    const len = try expr(mod, scope, .{ .ty = usize_type }, node_datas[node].lhs);
     const elem_type = try typeExpr(mod, scope, extra.elem_type);
-    const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted);
+    const sentinel = try expr(mod, scope, .{ .ty = elem_type }, extra.sentinel);
 
-    const result = try addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{
-        .len = len,
-        .sentinel = sentinel,
-        .elem_type = elem_type,
-    }, .{});
-    return rvalue(mod, scope, rl, result);
+    const result = try gz.addArrayTypeSentinel(len, elem_type, sentinel);
+    return rvalue(mod, scope, rl, result, node);
 }
 
 fn containerDecl(
src/Module.zig
@@ -1210,6 +1210,32 @@ pub const Scope = struct {
             return new_index + gz.zir_code.ref_start_index;
         }
 
+        pub fn addArrayTypeSentinel(
+            gz: *GenZir,
+            len: zir.Inst.Ref,
+            sentinel: zir.Inst.Ref,
+            elem_type: zir.Inst.Ref,
+        ) !zir.Inst.Ref {
+            const gpa = gz.zir_code.gpa;
+            try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
+            try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
+
+            const payload_index = try gz.zir_code.addExtra(zir.Inst.ArrayTypeSentinel{
+                .sentinel = sentinel,
+                .elem_type = elem_type,
+            });
+            const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
+            gz.zir_code.instructions.appendAssumeCapacity(.{
+                .tag = .array_type_sentinel,
+                .data = .{ .array_type_sentinel = .{
+                    .len = len,
+                    .payload_index = payload_index,
+                } },
+            });
+            gz.instructions.appendAssumeCapacity(new_index);
+            return new_index + gz.zir_code.ref_start_index;
+        }
+
         pub fn addUnTok(
             gz: *GenZir,
             tag: zir.Inst.Tag,