Commit 2a628fd401

Vexu <git@vexu.eu>
2020-08-28 13:55:04
stage2: astgen slice
1 parent ff7c6e1
Changed files (3)
src-self-hosted/astgen.zig
@@ -275,6 +275,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
         .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
         .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
         .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
+        .Slice => return rlWrap(mod, scope, rl, try sliceExpr(mod, scope, node.castTag(.Slice).?)),
         .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?),
         .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),
         .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?),
@@ -284,7 +285,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
         .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}),
         .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
         .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
-        .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
         .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),
         .ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}),
         .StructInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializer", .{}),
@@ -951,6 +951,36 @@ fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Array
     return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ElemPtr, .{ .array_ptr = array_ptr, .index = index }, .{}));
 }
 
+fn sliceExpr(mod: *Module, scope: *Scope, node: *ast.Node.Slice) InnerError!*zir.Inst {
+    const tree = scope.tree();
+    const src = tree.token_locs[node.rtoken].start;
+
+    const usize_type = try addZIRInstConst(mod, scope, src, .{
+        .ty = Type.initTag(.type),
+        .val = Value.initTag(.usize_type),
+    });
+
+    const array_ptr = try expr(mod, scope, .ref, node.lhs);
+    const start = try expr(mod, scope, .{ .ty = usize_type }, node.start);
+
+    if (node.end == null and node.sentinel == null) {
+        return try addZIRBinOp(mod, scope, src, .slice_start, array_ptr, start);
+    }
+
+    const end = if (node.end) |end| try expr(mod, scope, .{ .ty = usize_type }, end) else null;
+    // we could get the child type here, but it is easier to just do it in semantic analysis.
+    const sentinel = if (node.sentinel) |sentinel| try expr(mod, scope, .none, sentinel) else null;
+
+    return try addZIRInst(
+        mod,
+        scope,
+        src,
+        zir.Inst.Slice,
+        .{ .array_ptr = array_ptr, .start = start },
+        .{ .end = end, .sentinel = sentinel },
+    );
+}
+
 fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
     const tree = scope.tree();
     const src = tree.token_locs[node.rtoken].start;
src-self-hosted/zir.zig
@@ -231,6 +231,10 @@ pub const Inst = struct {
         const_slice_type,
         /// Create a pointer type with attributes
         ptr_type,
+        /// Slice operation `array_ptr[start..end:sentinel]`
+        slice,
+        /// Slice operation with just start `lhs[rhs..]`
+        slice_start,
         /// Write a value to a pointer. For loading, see `deref`.
         store,
         /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
@@ -343,6 +347,7 @@ pub const Inst = struct {
                 .xor,
                 .error_union_type,
                 .merge_error_sets,
+                .slice_start,
                 => BinOp,
 
                 .block,
@@ -380,6 +385,7 @@ pub const Inst = struct {
                 .ptr_type => PtrType,
                 .enum_literal => EnumLiteral,
                 .error_set => ErrorSet,
+                .slice => Slice,
             };
         }
 
@@ -481,6 +487,8 @@ pub const Inst = struct {
                 .error_union_type,
                 .bitnot,
                 .error_set,
+                .slice,
+                .slice_start,
                 => false,
 
                 .@"break",
@@ -961,6 +969,20 @@ pub const Inst = struct {
         },
         kw_args: struct {},
     };
+
+    pub const Slice = struct {
+        pub const base_tag = Tag.slice;
+        base: Inst,
+
+        positionals: struct {
+            array_ptr: *Inst,
+            start: *Inst,
+        },
+        kw_args: struct {
+            end: ?*Inst = null,
+            sentinel: ?*Inst = null,
+        },
+    };
 };
 
 pub const ErrorMsg = struct {
src-self-hosted/zir_sema.zig
@@ -132,6 +132,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
         .error_union_type => return analyzeInstErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
         .anyframe_type => return analyzeInstAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
         .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?),
+        .slice => return analyzeInstSlice(mod, scope, old_inst.castTag(.slice).?),
+        .slice_start => return analyzeInstSliceStart(mod, scope, old_inst.castTag(.slice_start).?),
     }
 }
 
@@ -1172,6 +1174,14 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
     return mod.fail(scope, inst.base.src, "TODO implement more analyze elemptr", .{});
 }
 
+fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerError!*Inst {
+    return mod.fail(scope, inst.base.src, "TODO implement analyzeInstSlice", .{});
+}
+
+fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
+    return mod.fail(scope, inst.base.src, "TODO implement analyzeInstSliceStart", .{});
+}
+
 fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
     return mod.fail(scope, inst.base.src, "TODO implement analyzeInstShl", .{});
 }