Commit da7fcfd158

Andrew Kelley <andrew@ziglang.org>
2021-10-14 01:31:07
stage2: implement Sema for elemVal for comptime slice
1 parent e851d89
Changed files (4)
src/Sema.zig
@@ -11048,11 +11048,16 @@ fn elemVal(
     switch (maybe_ptr_ty.zigTypeTag()) {
         .Pointer => switch (maybe_ptr_ty.ptrSize()) {
             .Slice => {
-                if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |slice_val| {
-                    _ = slice_val;
-                    return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known slice", .{});
-                }
-                try sema.requireRuntimeBlock(block, src);
+                const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array_maybe_ptr);
+                const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
+                const runtime_src = if (maybe_slice_val) |slice_val| rs: {
+                    const index_val = maybe_index_val orelse break :rs elem_index_src;
+                    const index = @intCast(usize, index_val.toUnsignedInt());
+                    const elem_val = try slice_val.elemValue(sema.arena, index);
+                    return sema.addConstant(maybe_ptr_ty.elemType2(), elem_val);
+                } else array_ptr_src;
+
+                try sema.requireRuntimeBlock(block, runtime_src);
                 return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index);
             },
             .Many, .C => {
src/type.zig
@@ -2448,6 +2448,7 @@ pub const Type = extern union {
     /// For ?[*]T,  returns T.
     /// For *T,     returns T.
     /// For [*]T,   returns T.
+    /// For []T,    returns T.
     pub fn elemType2(ty: Type) Type {
         return switch (ty.tag()) {
             .vector => ty.castTag(.vector).?.data.elem_type,
src/value.zig
@@ -1651,6 +1651,9 @@ pub const Value = extern union {
             .array => return val.castTag(.array).?.data[index],
             .slice => return val.castTag(.slice).?.data.ptr.elemValue(arena, index),
 
+            .decl_ref => return val.castTag(.decl_ref).?.data.val.elemValue(arena, index),
+            .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.val.elemValue(arena, index),
+
             else => unreachable,
         }
     }
test/behavior/slice.zig
@@ -3,3 +3,24 @@ const expect = std.testing.expect;
 const expectEqualSlices = std.testing.expectEqualSlices;
 const expectEqual = std.testing.expectEqual;
 const mem = std.mem;
+
+// comptime array passed as slice argument
+comptime {
+    const S = struct {
+        fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
+            var i: usize = start_index;
+            while (i < slice.len) : (i += 1) {
+                if (slice[i] == value) return i;
+            }
+            return null;
+        }
+
+        fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
+            return indexOfScalarPos(T, slice, 0, value);
+        }
+    };
+    const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
+    const list: []const type = &unsigned;
+    var pos = S.indexOfScalar(type, list, c_ulong).?;
+    if (pos != 1) @compileError("bad pos");
+}