diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-13 16:31:07 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-13 16:31:07 -0700 |
| commit | da7fcfd1586fa93c3d00815f60030e00ea583701 (patch) | |
| tree | d1f9b47a50df7ebff0b43a5ca98a406149821ddf | |
| parent | e851d89113a57064c38ed85722edc7f686d0c11a (diff) | |
| download | zig-da7fcfd1586fa93c3d00815f60030e00ea583701.tar.gz zig-da7fcfd1586fa93c3d00815f60030e00ea583701.zip | |
stage2: implement Sema for elemVal for comptime slice
| -rw-r--r-- | src/Sema.zig | 15 | ||||
| -rw-r--r-- | src/type.zig | 1 | ||||
| -rw-r--r-- | src/value.zig | 3 | ||||
| -rw-r--r-- | test/behavior/slice.zig | 21 |
4 files changed, 35 insertions, 5 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 2b7596861e..724fd48e99 100644 --- a/src/Sema.zig +++ b/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 => { diff --git a/src/type.zig b/src/type.zig index 814878c747..daffd4abee 100644 --- a/src/type.zig +++ b/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, diff --git a/src/value.zig b/src/value.zig index 8346fe5bc3..7996fcd976 100644 --- a/src/value.zig +++ b/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, } } diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 168754381a..5dc652d678 100644 --- a/test/behavior/slice.zig +++ b/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"); +} |
