| author | |
| committer | |
| log | 5ec0a7d8a5201fb35334ce62f82c5958b6ba296e |
| tree | 1874ea546d4b71e1c02f3cd37e7b2747f3f791e6 |
| parent | 9b74651cd2b799a73518de26c8293636f910c833 |
8 files changed, 72 insertions(+), 116 deletions(-)
lib/std/Io/Writer.zig+21-15| ... | @@ -1370,19 +1370,12 @@ pub fn printValue( | ... | @@ -1370,19 +1370,12 @@ pub fn printValue( |
| 1370 | }, | 1370 | }, |
| 1371 | .array => { | 1371 | .array => { |
| 1372 | if (!is_any) @compileError("cannot format array without a specifier (i.e. {s} or {any})"); | 1372 | if (!is_any) @compileError("cannot format array without a specifier (i.e. {s} or {any})"); |
| 1373 | if (max_depth == 0) return w.writeAll("{ ... }"); | 1373 | return printArray(w, fmt, options, &value, max_depth); |
| 1374 | try w.writeAll("{ "); | ||
| 1375 | for (value, 0..) |elem, i| { | ||
| 1376 | try w.printValue(fmt, options, elem, max_depth - 1); | ||
| 1377 | if (i < value.len - 1) { | ||
| 1378 | try w.writeAll(", "); | ||
| 1379 | } | ||
| 1380 | } | ||
| 1381 | try w.writeAll(" }"); | ||
| 1382 | }, | 1374 | }, |
| 1383 | .vector => { | 1375 | .vector => |vector| { |
| 1384 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 1376 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 1385 | return printVector(w, fmt, options, value, max_depth); | 1377 | const array: [vector.len]vector.child = value; |
| 1378 | return printArray(w, fmt, options, &array, max_depth); | ||
| 1386 | }, | 1379 | }, |
| 1387 | .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"), | 1380 | .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"), |
| 1388 | .type => { | 1381 | .type => { |
| ... | @@ -1436,12 +1429,25 @@ pub fn printVector( | ... | @@ -1436,12 +1429,25 @@ pub fn printVector( |
| 1436 | value: anytype, | 1429 | value: anytype, |
| 1437 | max_depth: usize, | 1430 | max_depth: usize, |
| 1438 | ) Error!void { | 1431 | ) Error!void { |
| 1439 | const len = @typeInfo(@TypeOf(value)).vector.len; | 1432 | const vector = @typeInfo(@TypeOf(value)).vector; |
| 1433 | const array: [vector.len]vector.child = value; | ||
| 1434 | return printArray(w, fmt, options, &array, max_depth); | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | pub fn printArray( | ||
| 1438 | w: *Writer, | ||
| 1439 | comptime fmt: []const u8, | ||
| 1440 | options: std.fmt.Options, | ||
| 1441 | ptr_to_array: anytype, | ||
| 1442 | max_depth: usize, | ||
| 1443 | ) Error!void { | ||
| 1440 | if (max_depth == 0) return w.writeAll("{ ... }"); | 1444 | if (max_depth == 0) return w.writeAll("{ ... }"); |
| 1441 | try w.writeAll("{ "); | 1445 | try w.writeAll("{ "); |
| 1442 | inline for (0..len) |i| { | 1446 | for (ptr_to_array, 0..) |elem, i| { |
| 1443 | try w.printValue(fmt, options, value[i], max_depth - 1); | 1447 | try w.printValue(fmt, options, elem, max_depth - 1); |
| 1444 | if (i < len - 1) try w.writeAll(", "); | 1448 | if (i < ptr_to_array.len - 1) { |
| 1449 | try w.writeAll(", "); | ||
| 1450 | } | ||
| 1445 | } | 1451 | } |
| 1446 | try w.writeAll(" }"); | 1452 | try w.writeAll(" }"); |
| 1447 | } | 1453 | } |
lib/std/crypto/chacha20.zig+10-10| ... | @@ -215,7 +215,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type | ... | @@ -215,7 +215,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type |
| 215 | } | 215 | } |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | fn hashToBytes(comptime dm: usize, out: *[64 * dm]u8, x: BlockVec) void { | 218 | fn hashToBytes(comptime dm: usize, out: *[64 * dm]u8, x: *const BlockVec) void { |
| 219 | inline for (0..dm) |d| { | 219 | inline for (0..dm) |d| { |
| 220 | for (0..4) |i| { | 220 | for (0..4) |i| { |
| 221 | mem.writeInt(u32, out[64 * d + 16 * i + 0 ..][0..4], x[i][0 + 4 * d], .little); | 221 | mem.writeInt(u32, out[64 * d + 16 * i + 0 ..][0..4], x[i][0 + 4 * d], .little); |
| ... | @@ -242,7 +242,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type | ... | @@ -242,7 +242,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type |
| 242 | while (degree >= d and i + 64 * d <= in.len) : (i += 64 * d) { | 242 | while (degree >= d and i + 64 * d <= in.len) : (i += 64 * d) { |
| 243 | chacha20Core(x[0..], ctx); | 243 | chacha20Core(x[0..], ctx); |
| 244 | contextFeedback(&x, ctx); | 244 | contextFeedback(&x, ctx); |
| 245 | hashToBytes(d, buf[0 .. 64 * d], x); | 245 | hashToBytes(d, buf[0 .. 64 * d], &x); |
| 246 | 246 | ||
| 247 | var xout = out[i..]; | 247 | var xout = out[i..]; |
| 248 | const xin = in[i..]; | 248 | const xin = in[i..]; |
| ... | @@ -266,7 +266,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type | ... | @@ -266,7 +266,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type |
| 266 | if (i < in.len) { | 266 | if (i < in.len) { |
| 267 | chacha20Core(x[0..], ctx); | 267 | chacha20Core(x[0..], ctx); |
| 268 | contextFeedback(&x, ctx); | 268 | contextFeedback(&x, ctx); |
| 269 | hashToBytes(1, buf[0..64], x); | 269 | hashToBytes(1, buf[0..64], &x); |
| 270 | 270 | ||
| 271 | var xout = out[i..]; | 271 | var xout = out[i..]; |
| 272 | const xin = in[i..]; | 272 | const xin = in[i..]; |
| ... | @@ -284,7 +284,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type | ... | @@ -284,7 +284,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type |
| 284 | while (degree >= d and i + 64 * d <= out.len) : (i += 64 * d) { | 284 | while (degree >= d and i + 64 * d <= out.len) : (i += 64 * d) { |
| 285 | chacha20Core(x[0..], ctx); | 285 | chacha20Core(x[0..], ctx); |
| 286 | contextFeedback(&x, ctx); | 286 | contextFeedback(&x, ctx); |
| 287 | hashToBytes(d, out[i..][0 .. 64 * d], x); | 287 | hashToBytes(d, out[i..][0 .. 64 * d], &x); |
| 288 | inline for (0..d) |d_| { | 288 | inline for (0..d) |d_| { |
| 289 | if (count64) { | 289 | if (count64) { |
| 290 | const next = @addWithOverflow(ctx[3][4 * d_], d); | 290 | const next = @addWithOverflow(ctx[3][4 * d_], d); |
| ... | @@ -301,7 +301,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type | ... | @@ -301,7 +301,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type |
| 301 | contextFeedback(&x, ctx); | 301 | contextFeedback(&x, ctx); |
| 302 | 302 | ||
| 303 | var buf: [64]u8 = undefined; | 303 | var buf: [64]u8 = undefined; |
| 304 | hashToBytes(1, buf[0..], x); | 304 | hashToBytes(1, buf[0..], &x); |
| 305 | @memcpy(out[i..], buf[0 .. out.len - i]); | 305 | @memcpy(out[i..], buf[0 .. out.len - i]); |
| 306 | } | 306 | } |
| 307 | } | 307 | } |
| ... | @@ -394,7 +394,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { | ... | @@ -394,7 +394,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { |
| 394 | } | 394 | } |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | fn hashToBytes(out: *[64]u8, x: BlockVec) void { | 397 | fn hashToBytes(out: *[64]u8, x: *const BlockVec) void { |
| 398 | for (0..4) |i| { | 398 | for (0..4) |i| { |
| 399 | mem.writeInt(u32, out[16 * i + 0 ..][0..4], x[i * 4 + 0], .little); | 399 | mem.writeInt(u32, out[16 * i + 0 ..][0..4], x[i * 4 + 0], .little); |
| 400 | mem.writeInt(u32, out[16 * i + 4 ..][0..4], x[i * 4 + 1], .little); | 400 | mem.writeInt(u32, out[16 * i + 4 ..][0..4], x[i * 4 + 1], .little); |
| ... | @@ -417,7 +417,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { | ... | @@ -417,7 +417,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { |
| 417 | while (i + 64 <= in.len) : (i += 64) { | 417 | while (i + 64 <= in.len) : (i += 64) { |
| 418 | chacha20Core(x[0..], ctx); | 418 | chacha20Core(x[0..], ctx); |
| 419 | contextFeedback(&x, ctx); | 419 | contextFeedback(&x, ctx); |
| 420 | hashToBytes(buf[0..], x); | 420 | hashToBytes(buf[0..], &x); |
| 421 | 421 | ||
| 422 | var xout = out[i..]; | 422 | var xout = out[i..]; |
| 423 | const xin = in[i..]; | 423 | const xin = in[i..]; |
| ... | @@ -438,7 +438,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { | ... | @@ -438,7 +438,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { |
| 438 | if (i < in.len) { | 438 | if (i < in.len) { |
| 439 | chacha20Core(x[0..], ctx); | 439 | chacha20Core(x[0..], ctx); |
| 440 | contextFeedback(&x, ctx); | 440 | contextFeedback(&x, ctx); |
| 441 | hashToBytes(buf[0..], x); | 441 | hashToBytes(buf[0..], &x); |
| 442 | 442 | ||
| 443 | var xout = out[i..]; | 443 | var xout = out[i..]; |
| 444 | const xin = in[i..]; | 444 | const xin = in[i..]; |
| ... | @@ -455,7 +455,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { | ... | @@ -455,7 +455,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { |
| 455 | while (i + 64 <= out.len) : (i += 64) { | 455 | while (i + 64 <= out.len) : (i += 64) { |
| 456 | chacha20Core(x[0..], ctx); | 456 | chacha20Core(x[0..], ctx); |
| 457 | contextFeedback(&x, ctx); | 457 | contextFeedback(&x, ctx); |
| 458 | hashToBytes(out[i..][0..64], x); | 458 | hashToBytes(out[i..][0..64], &x); |
| 459 | if (count64) { | 459 | if (count64) { |
| 460 | const next = @addWithOverflow(ctx[12], 1); | 460 | const next = @addWithOverflow(ctx[12], 1); |
| 461 | ctx[12] = next[0]; | 461 | ctx[12] = next[0]; |
| ... | @@ -469,7 +469,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { | ... | @@ -469,7 +469,7 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { |
| 469 | contextFeedback(&x, ctx); | 469 | contextFeedback(&x, ctx); |
| 470 | 470 | ||
| 471 | var buf: [64]u8 = undefined; | 471 | var buf: [64]u8 = undefined; |
| 472 | hashToBytes(buf[0..], x); | 472 | hashToBytes(buf[0..], &x); |
| 473 | @memcpy(out[i..], buf[0 .. out.len - i]); | 473 | @memcpy(out[i..], buf[0 .. out.len - i]); |
| 474 | } | 474 | } |
| 475 | } | 475 | } |
lib/std/json/static.zig+5-24| ... | @@ -440,10 +440,11 @@ pub fn innerParse( | ... | @@ -440,10 +440,11 @@ pub fn innerParse( |
| 440 | } | 440 | } |
| 441 | }, | 441 | }, |
| 442 | 442 | ||
| 443 | .vector => |vecInfo| { | 443 | .vector => |vector_info| { |
| 444 | switch (try source.peekNextTokenType()) { | 444 | switch (try source.peekNextTokenType()) { |
| 445 | .array_begin => { | 445 | .array_begin => { |
| 446 | return internalParseVector(T, vecInfo.child, vecInfo.len, allocator, source, options); | 446 | const A = [vector_info.len]vector_info.child; |
| 447 | return try internalParseArray(A, vector_info.child, allocator, source, options); | ||
| 447 | }, | 448 | }, |
| 448 | else => return error.UnexpectedToken, | 449 | else => return error.UnexpectedToken, |
| 449 | } | 450 | } |
| ... | @@ -535,26 +536,6 @@ fn internalParseArray( | ... | @@ -535,26 +536,6 @@ fn internalParseArray( |
| 535 | return r; | 536 | return r; |
| 536 | } | 537 | } |
| 537 | 538 | ||
| 538 | fn internalParseVector( | ||
| 539 | comptime T: type, | ||
| 540 | comptime Child: type, | ||
| 541 | comptime len: comptime_int, | ||
| 542 | allocator: Allocator, | ||
| 543 | source: anytype, | ||
| 544 | options: ParseOptions, | ||
| 545 | ) !T { | ||
| 546 | assert(.array_begin == try source.next()); | ||
| 547 | |||
| 548 | var r: T = undefined; | ||
| 549 | inline for (0..len) |i| { | ||
| 550 | r[i] = try innerParse(Child, allocator, source, options); | ||
| 551 | } | ||
| 552 | |||
| 553 | if (.array_end != try source.next()) return error.UnexpectedToken; | ||
| 554 | |||
| 555 | return r; | ||
| 556 | } | ||
| 557 | |||
| 558 | /// This is an internal function called recursively | 539 | /// This is an internal function called recursively |
| 559 | /// during the implementation of `parseFromValueLeaky`. | 540 | /// during the implementation of `parseFromValueLeaky`. |
| 560 | /// It is exposed primarily to enable custom `jsonParseFromValue()` methods to call back into the `parseFromValue*` system, | 541 | /// It is exposed primarily to enable custom `jsonParseFromValue()` methods to call back into the `parseFromValue*` system, |
| ... | @@ -587,12 +568,12 @@ pub fn innerParseFromValue( | ... | @@ -587,12 +568,12 @@ pub fn innerParseFromValue( |
| 587 | if (@round(f) != f) return error.InvalidNumber; | 568 | if (@round(f) != f) return error.InvalidNumber; |
| 588 | if (f > @as(@TypeOf(f), @floatFromInt(std.math.maxInt(T)))) return error.Overflow; | 569 | if (f > @as(@TypeOf(f), @floatFromInt(std.math.maxInt(T)))) return error.Overflow; |
| 589 | if (f < @as(@TypeOf(f), @floatFromInt(std.math.minInt(T)))) return error.Overflow; | 570 | if (f < @as(@TypeOf(f), @floatFromInt(std.math.minInt(T)))) return error.Overflow; |
| 590 | return @as(T, @intFromFloat(f)); | 571 | return @intFromFloat(f); |
| 591 | }, | 572 | }, |
| 592 | .integer => |i| { | 573 | .integer => |i| { |
| 593 | if (i > std.math.maxInt(T)) return error.Overflow; | 574 | if (i > std.math.maxInt(T)) return error.Overflow; |
| 594 | if (i < std.math.minInt(T)) return error.Overflow; | 575 | if (i < std.math.minInt(T)) return error.Overflow; |
| 595 | return @as(T, @intCast(i)); | 576 | return @intCast(i); |
| 596 | }, | 577 | }, |
| 597 | .number_string, .string => |s| { | 578 | .number_string, .string => |s| { |
| 598 | return sliceToInt(T, s); | 579 | return sliceToInt(T, s); |
lib/std/meta.zig+1-6| ... | @@ -742,12 +742,7 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool { | ... | @@ -742,12 +742,7 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool { |
| 742 | if (!eql(e, b[i])) return false; | 742 | if (!eql(e, b[i])) return false; |
| 743 | return true; | 743 | return true; |
| 744 | }, | 744 | }, |
| 745 | .vector => |info| { | 745 | .vector => return @reduce(.And, a == b), |
| 746 | inline for (0..info.len) |i| { | ||
| 747 | if (a[i] != b[i]) return false; | ||
| 748 | } | ||
| 749 | return true; | ||
| 750 | }, | ||
| 751 | .pointer => |info| { | 746 | .pointer => |info| { |
| 752 | return switch (info.size) { | 747 | return switch (info.size) { |
| 753 | .one, .many, .c => a == b, | 748 | .one, .many, .c => a == b, |
lib/std/testing.zig+3-8| ... | @@ -135,14 +135,9 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void { | ... | @@ -135,14 +135,9 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void { |
| 135 | .array => |array| try expectEqualSlices(array.child, &expected, &actual), | 135 | .array => |array| try expectEqualSlices(array.child, &expected, &actual), |
| 136 | 136 | ||
| 137 | .vector => |info| { | 137 | .vector => |info| { |
| 138 | inline for (0..info.len) |i| { | 138 | const expect_array: [info.len]info.child = expected; |
| 139 | if (expected[i] != actual[i]) { | 139 | const actual_array: [info.len]info.child = actual; |
| 140 | print("index {d} incorrect. expected {any}, found {any}\n", .{ | 140 | try expectEqualSlices(info.child, &expect_array, &actual_array); |
| 141 | i, expected[i], actual[i], | ||
| 142 | }); | ||
| 143 | return error.TestExpectedEqual; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | }, | 141 | }, |
| 147 | 142 | ||
| 148 | .@"struct" => |structType| { | 143 | .@"struct" => |structType| { |
lib/std/zon/Serializer.zig+15-16| ... | @@ -157,13 +157,11 @@ pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOption | ... | @@ -157,13 +157,11 @@ pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOption |
| 157 | } | 157 | } |
| 158 | }, | 158 | }, |
| 159 | .array => { | 159 | .array => { |
| 160 | var container = try self.beginTuple( | 160 | try valueArbitraryDepthArray(self, @TypeOf(val), &val, options); |
| 161 | .{ .whitespace_style = .{ .fields = val.len } }, | 161 | }, |
| 162 | ); | 162 | .vector => |vector| { |
| 163 | for (val) |item_val| { | 163 | const array: [vector.len]vector.child = val; |
| 164 | try container.fieldArbitraryDepth(item_val, options); | 164 | try valueArbitraryDepthArray(self, @TypeOf(array), &array, options); |
| 165 | } | ||
| 166 | try container.end(); | ||
| 167 | }, | 165 | }, |
| 168 | .@"struct" => |@"struct"| if (@"struct".is_tuple) { | 166 | .@"struct" => |@"struct"| if (@"struct".is_tuple) { |
| 169 | var container = try self.beginTuple( | 167 | var container = try self.beginTuple( |
| ... | @@ -231,20 +229,21 @@ pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOption | ... | @@ -231,20 +229,21 @@ pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOption |
| 231 | } else { | 229 | } else { |
| 232 | try self.writer.writeAll("null"); | 230 | try self.writer.writeAll("null"); |
| 233 | }, | 231 | }, |
| 234 | .vector => |vector| { | ||
| 235 | var container = try self.beginTuple( | ||
| 236 | .{ .whitespace_style = .{ .fields = vector.len } }, | ||
| 237 | ); | ||
| 238 | inline for (0..vector.len) |i| { | ||
| 239 | try container.fieldArbitraryDepth(val[i], options); | ||
| 240 | } | ||
| 241 | try container.end(); | ||
| 242 | }, | ||
| 243 | 232 | ||
| 244 | else => comptime unreachable, | 233 | else => comptime unreachable, |
| 245 | } | 234 | } |
| 246 | } | 235 | } |
| 247 | 236 | ||
| 237 | fn valueArbitraryDepthArray(s: *Serializer, comptime A: type, array: *const A, options: ValueOptions) Error!void { | ||
| 238 | var container = try s.beginTuple( | ||
| 239 | .{ .whitespace_style = .{ .fields = array.len } }, | ||
| 240 | ); | ||
| 241 | for (array) |elem| { | ||
| 242 | try container.fieldArbitraryDepth(elem, options); | ||
| 243 | } | ||
| 244 | try container.end(); | ||
| 245 | } | ||
| 246 | |||
| 248 | /// Serialize an integer. | 247 | /// Serialize an integer. |
| 249 | pub fn int(self: *Serializer, val: anytype) Error!void { | 248 | pub fn int(self: *Serializer, val: anytype) Error!void { |
| 250 | try self.writer.printInt(val, 10, .lower, .{}); | 249 | try self.writer.printInt(val, 10, .lower, .{}); |
lib/std/zon/parse.zig+16-33| ... | @@ -430,8 +430,12 @@ pub fn free(gpa: Allocator, value: anytype) void { | ... | @@ -430,8 +430,12 @@ pub fn free(gpa: Allocator, value: anytype) void { |
| 430 | .many, .c => comptime unreachable, | 430 | .many, .c => comptime unreachable, |
| 431 | } | 431 | } |
| 432 | }, | 432 | }, |
| 433 | .array => for (value) |item| { | 433 | .array => { |
| 434 | free(gpa, item); | 434 | freeArray(gpa, @TypeOf(value), &value); |
| 435 | }, | ||
| 436 | .vector => |vector| { | ||
| 437 | const array: [vector.len]vector.child = value; | ||
| 438 | freeArray(gpa, @TypeOf(array), &array); | ||
| 435 | }, | 439 | }, |
| 436 | .@"struct" => |@"struct"| inline for (@"struct".fields) |field| { | 440 | .@"struct" => |@"struct"| inline for (@"struct".fields) |field| { |
| 437 | free(gpa, @field(value, field.name)); | 441 | free(gpa, @field(value, field.name)); |
| ... | @@ -446,12 +450,15 @@ pub fn free(gpa: Allocator, value: anytype) void { | ... | @@ -446,12 +450,15 @@ pub fn free(gpa: Allocator, value: anytype) void { |
| 446 | .optional => if (value) |some| { | 450 | .optional => if (value) |some| { |
| 447 | free(gpa, some); | 451 | free(gpa, some); |
| 448 | }, | 452 | }, |
| 449 | .vector => |vector| inline for (0..vector.len) |i| free(gpa, value[i]), | ||
| 450 | .void => {}, | 453 | .void => {}, |
| 451 | else => comptime unreachable, | 454 | else => comptime unreachable, |
| 452 | } | 455 | } |
| 453 | } | 456 | } |
| 454 | 457 | ||
| 458 | fn freeArray(gpa: Allocator, comptime A: type, array: *const A) void { | ||
| 459 | for (array) |elem| free(gpa, elem); | ||
| 460 | } | ||
| 461 | |||
| 455 | fn requiresAllocator(T: type) bool { | 462 | fn requiresAllocator(T: type) bool { |
| 456 | _ = valid_types; | 463 | _ = valid_types; |
| 457 | return switch (@typeInfo(T)) { | 464 | return switch (@typeInfo(T)) { |
| ... | @@ -521,12 +528,15 @@ const Parser = struct { | ... | @@ -521,12 +528,15 @@ const Parser = struct { |
| 521 | else => comptime unreachable, | 528 | else => comptime unreachable, |
| 522 | }, | 529 | }, |
| 523 | .array => return self.parseArray(T, node), | 530 | .array => return self.parseArray(T, node), |
| 531 | .vector => |vector| { | ||
| 532 | const A = [vector.len]vector.child; | ||
| 533 | return try self.parseArray(A, node); | ||
| 534 | }, | ||
| 524 | .@"struct" => |@"struct"| if (@"struct".is_tuple) | 535 | .@"struct" => |@"struct"| if (@"struct".is_tuple) |
| 525 | return self.parseTuple(T, node) | 536 | return self.parseTuple(T, node) |
| 526 | else | 537 | else |
| 527 | return self.parseStruct(T, node), | 538 | return self.parseStruct(T, node), |
| 528 | .@"union" => return self.parseUnion(T, node), | 539 | .@"union" => return self.parseUnion(T, node), |
| 529 | .vector => return self.parseVector(T, node), | ||
| 530 | 540 | ||
| 531 | else => comptime unreachable, | 541 | else => comptime unreachable, |
| 532 | } | 542 | } |
| ... | @@ -999,33 +1009,6 @@ const Parser = struct { | ... | @@ -999,33 +1009,6 @@ const Parser = struct { |
| 999 | } | 1009 | } |
| 1000 | } | 1010 | } |
| 1001 | 1011 | ||
| 1002 | fn parseVector(self: *@This(), T: type, node: Zoir.Node.Index) !T { | ||
| 1003 | const vector_info = @typeInfo(T).vector; | ||
| 1004 | |||
| 1005 | const nodes: Zoir.Node.Index.Range = switch (node.get(self.zoir)) { | ||
| 1006 | .array_literal => |nodes| nodes, | ||
| 1007 | .empty_literal => .{ .start = node, .len = 0 }, | ||
| 1008 | else => return error.WrongType, | ||
| 1009 | }; | ||
| 1010 | |||
| 1011 | var result: T = undefined; | ||
| 1012 | |||
| 1013 | if (nodes.len != vector_info.len) { | ||
| 1014 | return self.failNodeFmt( | ||
| 1015 | node, | ||
| 1016 | "expected {} vector elements; found {}", | ||
| 1017 | .{ vector_info.len, nodes.len }, | ||
| 1018 | ); | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | inline for (0..vector_info.len) |i| { | ||
| 1022 | errdefer inline for (0..i) |j| free(self.gpa, result[j]); | ||
| 1023 | result[i] = try self.parseExpr(vector_info.child, nodes.at(@intCast(i))); | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | return result; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | fn failTokenFmt( | 1012 | fn failTokenFmt( |
| 1030 | self: @This(), | 1013 | self: @This(), |
| 1031 | token: Ast.TokenIndex, | 1014 | token: Ast.TokenIndex, |
| ... | @@ -3206,7 +3189,7 @@ test "std.zon vector" { | ... | @@ -3206,7 +3189,7 @@ test "std.zon vector" { |
| 3206 | fromSlice(@Vector(2, f32), gpa, ".{0.5}", &diag, .{}), | 3189 | fromSlice(@Vector(2, f32), gpa, ".{0.5}", &diag, .{}), |
| 3207 | ); | 3190 | ); |
| 3208 | try std.testing.expectFmt( | 3191 | try std.testing.expectFmt( |
| 3209 | "1:2: error: expected 2 vector elements; found 1\n", | 3192 | "1:2: error: expected 2 array elements; found 1\n", |
| 3210 | "{f}", | 3193 | "{f}", |
| 3211 | .{diag}, | 3194 | .{diag}, |
| 3212 | ); | 3195 | ); |
| ... | @@ -3221,7 +3204,7 @@ test "std.zon vector" { | ... | @@ -3221,7 +3204,7 @@ test "std.zon vector" { |
| 3221 | fromSlice(@Vector(2, f32), gpa, ".{0.5, 1.5, 2.5}", &diag, .{}), | 3204 | fromSlice(@Vector(2, f32), gpa, ".{0.5, 1.5, 2.5}", &diag, .{}), |
| 3222 | ); | 3205 | ); |
| 3223 | try std.testing.expectFmt( | 3206 | try std.testing.expectFmt( |
| 3224 | "1:2: error: expected 2 vector elements; found 3\n", | 3207 | "1:13: error: index 2 outside of array of length 2\n", |
| 3225 | "{f}", | 3208 | "{f}", |
| 3226 | .{diag}, | 3209 | .{diag}, |
| 3227 | ); | 3210 | ); |
test/behavior/math.zig+1-4| ... | @@ -139,10 +139,7 @@ fn expectVectorsEqual(a: anytype, b: anytype) !void { | ... | @@ -139,10 +139,7 @@ fn expectVectorsEqual(a: anytype, b: anytype) !void { |
| 139 | const len_a = @typeInfo(@TypeOf(a)).vector.len; | 139 | const len_a = @typeInfo(@TypeOf(a)).vector.len; |
| 140 | const len_b = @typeInfo(@TypeOf(b)).vector.len; | 140 | const len_b = @typeInfo(@TypeOf(b)).vector.len; |
| 141 | try expect(len_a == len_b); | 141 | try expect(len_a == len_b); |
| 142 | 142 | try expect(@reduce(.And, a == b)); | |
| 143 | inline for (0..len_a) |i| { | ||
| 144 | try expect(a[i] == b[i]); | ||
| 145 | } | ||
| 146 | } | 143 | } |
| 147 | 144 | ||
| 148 | test "@ctz" { | 145 | test "@ctz" { |