| ... | @@ -42,6 +42,7 @@ pub const FromOptions = struct { | ... | @@ -42,6 +42,7 @@ pub const FromOptions = struct { |
| 42 | .ignore_unknown_fields = self.ignore_unknown_fields, | 42 | .ignore_unknown_fields = self.ignore_unknown_fields, |
| 43 | .ignore_missing_fields = false, | 43 | .ignore_missing_fields = false, |
| 44 | .free_on_error = self.free_on_error, | 44 | .free_on_error = self.free_on_error, |
| | 45 | .free_on_write = false, |
| 45 | }; | 46 | }; |
| 46 | } | 47 | } |
| 47 | }; | 48 | }; |
| ... | @@ -50,12 +51,17 @@ pub const FromOptions = struct { | ... | @@ -50,12 +51,17 @@ pub const FromOptions = struct { |
| 50 | pub const UpdateFromOptions = struct { | 51 | pub const UpdateFromOptions = struct { |
| 51 | /// If true, unknown fields do not error. | 52 | /// If true, unknown fields do not error. |
| 52 | ignore_unknown_fields: bool = false, | 53 | ignore_unknown_fields: bool = false, |
| | 54 | /// If true, the old values of overriden fields are freed. You may want to turn this off if you |
| | 55 | /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals. |
| | 56 | /// In this case, you can use arena allocation. |
| | 57 | free_on_write: bool = true, |
| 53 | | 58 | |
| 54 | fn toParserOptions(self: UpdateFromOptions) Parser.Options { | 59 | fn toParserOptions(self: UpdateFromOptions) Parser.Options { |
| 55 | return .{ | 60 | return .{ |
| 56 | .ignore_unknown_fields = self.ignore_unknown_fields, | 61 | .ignore_unknown_fields = self.ignore_unknown_fields, |
| 57 | .ignore_missing_fields = true, | 62 | .ignore_missing_fields = true, |
| 58 | .free_on_error = false, | 63 | .free_on_error = false, |
| | 64 | .free_on_write = true, |
| 59 | }; | 65 | }; |
| 60 | } | 66 | } |
| 61 | }; | 67 | }; |
| ... | @@ -313,7 +319,8 @@ pub fn fromSlice( | ... | @@ -313,7 +319,8 @@ pub fn fromSlice( |
| 313 | } | 319 | } |
| 314 | | 320 | |
| 315 | /// Similar to `fromSlice`, but updates an existing value `current`. Fields not specified by ZON are | 321 | /// Similar to `fromSlice`, but updates an existing value `current`. Fields not specified by ZON are |
| 316 | /// left at their current values. Pointers are replaced with new values not mutated in place. | 322 | /// left at their current values. Pointers are replaced with new values not mutated in place. On |
| | 323 | /// failure, values that were updated prior to the failure are left updated. |
| 317 | pub fn updateFromSlice( | 324 | pub fn updateFromSlice( |
| 318 | T: type, | 325 | T: type, |
| 319 | gpa: Allocator, | 326 | gpa: Allocator, |
| ... | @@ -340,39 +347,39 @@ pub fn fromSliceAlloc( | ... | @@ -340,39 +347,39 @@ pub fn fromSliceAlloc( |
| 340 | return result; | 347 | return result; |
| 341 | } | 348 | } |
| 342 | | 349 | |
| 343 | /// Like updateFromSlice`, but the result may contain pointers. Requires an arena for cleanup. | 350 | /// Like updateFromSlice`, but the result may contain pointers. |
| 344 | pub fn updateFromSliceAlloc( | 351 | pub fn updateFromSliceAlloc( |
| 345 | T: type, | 352 | T: type, |
| 346 | arena: Allocator, | 353 | gpa: Allocator, |
| 347 | current: *T, | 354 | current: *T, |
| 348 | source: [:0]const u8, | 355 | source: [:0]const u8, |
| 349 | diag: ?*Diagnostics, | 356 | diag: ?*Diagnostics, |
| 350 | options: UpdateFromOptions, | 357 | options: UpdateFromOptions, |
| 351 | ) error{ OutOfMemory, ParseZon }!void { | 358 | ) error{ OutOfMemory, ParseZon }!void { |
| 352 | try parseSliceAlloc(T, current, arena, source, diag, options.toParserOptions()); | 359 | try parseSliceAlloc(T, current, gpa, source, diag, options.toParserOptions()); |
| 353 | } | 360 | } |
| 354 | | 361 | |
| 355 | fn parseSliceAlloc( | 362 | fn parseSliceAlloc( |
| 356 | T: type, | 363 | T: type, |
| 357 | current: *T, | 364 | current: *T, |
| 358 | arena: Allocator, | 365 | gpa: Allocator, |
| 359 | source: [:0]const u8, | 366 | source: [:0]const u8, |
| 360 | diag: ?*Diagnostics, | 367 | diag: ?*Diagnostics, |
| 361 | options: Parser.Options, | 368 | options: Parser.Options, |
| 362 | ) error{ OutOfMemory, ParseZon }!void { | 369 | ) error{ OutOfMemory, ParseZon }!void { |
| 363 | if (diag) |s| s.assertEmpty(); | 370 | if (diag) |s| s.assertEmpty(); |
| 364 | | 371 | |
| 365 | var ast = try std.zig.Ast.parse(arena, source, .{ .mode = .zon }); | 372 | var ast = try std.zig.Ast.parse(gpa, source, .{ .mode = .zon }); |
| 366 | defer if (diag == null) ast.deinit(arena); | 373 | defer if (diag == null) ast.deinit(gpa); |
| 367 | if (diag) |s| s.ast = ast; | 374 | if (diag) |s| s.ast = ast; |
| 368 | | 375 | |
| 369 | // If there's no diagnostics, Zoir exists for the lifetime of this function. If there is a | 376 | // If there's no diagnostics, Zoir exists for the lifetime of this function. If there is a |
| 370 | // diagnostics, ownership is transferred to diagnostics. | 377 | // diagnostics, ownership is transferred to diagnostics. |
| 371 | var zoir = try ZonGen.generate(arena, ast, .{ .parse_str_lits = false }); | 378 | var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false }); |
| 372 | defer if (diag == null) zoir.deinit(arena); | 379 | defer if (diag == null) zoir.deinit(gpa); |
| 373 | | 380 | |
| 374 | if (diag) |s| s.* = .{}; | 381 | if (diag) |s| s.* = .{}; |
| 375 | try parseZoirAlloc(T, arena, current, ast, zoir, diag, options); | 382 | try parseZoirAlloc(T, gpa, current, ast, zoir, diag, options); |
| 376 | } | 383 | } |
| 377 | | 384 | |
| 378 | /// Like `fromSlice`, but operates on `Zoir` instead of ZON source. | 385 | /// Like `fromSlice`, but operates on `Zoir` instead of ZON source. |
| ... | @@ -440,14 +447,14 @@ pub fn fromZoirAlloc( | ... | @@ -440,14 +447,14 @@ pub fn fromZoirAlloc( |
| 440 | /// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source. | 447 | /// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source. |
| 441 | pub fn updateFromZoirAlloc( | 448 | pub fn updateFromZoirAlloc( |
| 442 | T: type, | 449 | T: type, |
| 443 | arena: Allocator, | 450 | gpa: Allocator, |
| 444 | current: *T, | 451 | current: *T, |
| 445 | ast: Ast, | 452 | ast: Ast, |
| 446 | zoir: Zoir, | 453 | zoir: Zoir, |
| 447 | diag: ?*Diagnostics, | 454 | diag: ?*Diagnostics, |
| 448 | options: UpdateFromOptions, | 455 | options: UpdateFromOptions, |
| 449 | ) error{ OutOfMemory, ParseZon }!void { | 456 | ) error{ OutOfMemory, ParseZon }!void { |
| 450 | try parseZoirAlloc(T, arena, current, ast, zoir, diag, options.toParserOptions()); | 457 | try parseZoirAlloc(T, gpa, current, ast, zoir, diag, options.toParserOptions()); |
| 451 | } | 458 | } |
| 452 | | 459 | |
| 453 | fn parseZoirAlloc( | 460 | fn parseZoirAlloc( |
| ... | @@ -534,7 +541,7 @@ pub fn fromZoirNodeAlloc( | ... | @@ -534,7 +541,7 @@ pub fn fromZoirNodeAlloc( |
| 534 | /// Like `updateZoirNodeAlloc`, but the parse starts at `node` instead of root. | 541 | /// Like `updateZoirNodeAlloc`, but the parse starts at `node` instead of root. |
| 535 | pub fn updateFromZoirNodeAlloc( | 542 | pub fn updateFromZoirNodeAlloc( |
| 536 | T: type, | 543 | T: type, |
| 537 | arena: Allocator, | 544 | gpa: Allocator, |
| 538 | current: *T, | 545 | current: *T, |
| 539 | ast: Ast, | 546 | ast: Ast, |
| 540 | zoir: Zoir, | 547 | zoir: Zoir, |
| ... | @@ -542,7 +549,7 @@ pub fn updateFromZoirNodeAlloc( | ... | @@ -542,7 +549,7 @@ pub fn updateFromZoirNodeAlloc( |
| 542 | diag: ?*Diagnostics, | 549 | diag: ?*Diagnostics, |
| 543 | options: UpdateFromOptions, | 550 | options: UpdateFromOptions, |
| 544 | ) error{ OutOfMemory, ParseZon }!void { | 551 | ) error{ OutOfMemory, ParseZon }!void { |
| 545 | return parseZoirNodeAlloc(T, arena, current, ast, zoir, node, diag, options.toParserOptions()); | 552 | return parseZoirNodeAlloc(T, gpa, current, ast, zoir, node, diag, options.toParserOptions()); |
| 546 | } | 553 | } |
| 547 | | 554 | |
| 548 | fn parseZoirNodeAlloc( | 555 | fn parseZoirNodeAlloc( |
| ... | @@ -667,6 +674,7 @@ const Parser = struct { | ... | @@ -667,6 +674,7 @@ const Parser = struct { |
| 667 | pub const Options = struct { | 674 | pub const Options = struct { |
| 668 | ignore_unknown_fields: bool, | 675 | ignore_unknown_fields: bool, |
| 669 | free_on_error: bool, | 676 | free_on_error: bool, |
| | 677 | free_on_write: bool, |
| 670 | ignore_missing_fields: bool, | 678 | ignore_missing_fields: bool, |
| 671 | }; | 679 | }; |
| 672 | | 680 | |
| ... | @@ -687,21 +695,22 @@ const Parser = struct { | ... | @@ -687,21 +695,22 @@ const Parser = struct { |
| 687 | out: anytype, | 695 | out: anytype, |
| 688 | ) ParseExprInnerError!void { | 696 | ) ParseExprInnerError!void { |
| 689 | if (@TypeOf(out.*) == Zoir.Node.Index) { | 697 | if (@TypeOf(out.*) == Zoir.Node.Index) { |
| 690 | out.* = node; | 698 | self.write(out, node); |
| 691 | return; | 699 | return; |
| 692 | } | 700 | } |
| 693 | | 701 | |
| 694 | switch (@typeInfo(@TypeOf(out.*))) { | 702 | switch (@typeInfo(@TypeOf(out.*))) { |
| 695 | .optional => |optional| if (node.get(self.zoir) == .null) { | 703 | .optional => |optional| if (node.get(self.zoir) == .null) { |
| 696 | out.* = null; | 704 | self.write(out, null); |
| 697 | } else { | 705 | } else { |
| 698 | out.* = @as(optional.child, undefined); // Make non-null | 706 | var new: optional.child = undefined; |
| 699 | try self.parseExprInnerInto(node, &out.*.?); // Parse value into non-null pointer | 707 | try self.parseExprInnerInto(node, &new); |
| | 708 | self.write(out, new); |
| 700 | }, | 709 | }, |
| 701 | .bool => out.* = try self.parseBool(node), | 710 | .bool => self.write(out, try self.parseBool(node)), |
| 702 | .int => out.* = try self.parseInt(@TypeOf(out.*), node), | 711 | .int => self.write(out, try self.parseInt(@TypeOf(out.*), node)), |
| 703 | .float => out.* = try self.parseFloat(@TypeOf(out.*), node), | 712 | .float => self.write(out, try self.parseFloat(@TypeOf(out.*), node)), |
| 704 | .@"enum" => out.* = try self.parseEnumLiteral(@TypeOf(out.*), node), | 713 | .@"enum" => self.write(out, try self.parseEnumLiteral(@TypeOf(out.*), node)), |
| 705 | .pointer => |pointer| switch (pointer.size) { | 714 | .pointer => |pointer| switch (pointer.size) { |
| 706 | .one => { | 715 | .one => { |
| 707 | const slice = try self.gpa.alignedAlloc( | 716 | const slice = try self.gpa.alignedAlloc( |
| ... | @@ -710,13 +719,23 @@ const Parser = struct { | ... | @@ -710,13 +719,23 @@ const Parser = struct { |
| 710 | 1, | 719 | 1, |
| 711 | ); | 720 | ); |
| 712 | errdefer self.gpa.free(slice); | 721 | errdefer self.gpa.free(slice); |
| 713 | const ptr = &slice[0]; | 722 | const new = &slice[0]; |
| 714 | self.pointer_depth += 1; | 723 | { |
| 715 | defer self.pointer_depth -= 1; | 724 | self.pointer_depth += 1; |
| 716 | try self.parseExprInnerInto(node, ptr); | 725 | defer self.pointer_depth -= 1; |
| 717 | out.* = ptr; | 726 | try self.parseExprInnerInto(node, new); |
| | 727 | } |
| | 728 | self.write(out, new); |
| | 729 | }, |
| | 730 | .slice => { |
| | 731 | const new = b: { |
| | 732 | self.pointer_depth += 1; |
| | 733 | defer self.pointer_depth -= 1; |
| | 734 | const new = try self.parseSlicePointer(@TypeOf(out.*), node); |
| | 735 | break :b new; |
| | 736 | }; |
| | 737 | self.write(out, new); |
| 718 | }, | 738 | }, |
| 719 | .slice => out.* = try self.parseSlicePointer(@TypeOf(out.*), node), | | |
| 720 | else => comptime unreachable, | 739 | else => comptime unreachable, |
| 721 | }, | 740 | }, |
| 722 | .array => try self.parseArrayInto(node, out), | 741 | .array => try self.parseArrayInto(node, out), |
| ... | @@ -994,7 +1013,7 @@ const Parser = struct { | ... | @@ -994,7 +1013,7 @@ const Parser = struct { |
| 994 | const vector = @typeInfo(@TypeOf(out.*)).vector; | 1013 | const vector = @typeInfo(@TypeOf(out.*)).vector; |
| 995 | var array: [vector.len]vector.child = undefined; | 1014 | var array: [vector.len]vector.child = undefined; |
| 996 | try self.parseArrayInto(node, &array); | 1015 | try self.parseArrayInto(node, &array); |
| 997 | out.* = array; | 1016 | self.write(out, array); |
| 998 | } | 1017 | } |
| 999 | | 1018 | |
| 1000 | fn parseStructInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void { | 1019 | fn parseStructInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void { |
| ... | @@ -1166,7 +1185,7 @@ const Parser = struct { | ... | @@ -1166,7 +1185,7 @@ const Parser = struct { |
| 1166 | return self.failNode(node, "expected union"); | 1185 | return self.failNode(node, "expected union"); |
| 1167 | | 1186 | |
| 1168 | // Instantiate the union | 1187 | // Instantiate the union |
| 1169 | out.* = @unionInit(@TypeOf(out.*), @"union".field_names[i], {}); | 1188 | self.write(out, @unionInit(@TypeOf(out.*), @"union".field_names[i], {})); |
| 1170 | }, | 1189 | }, |
| 1171 | else => unreachable, // Can't be out of bounds | 1190 | else => unreachable, // Can't be out of bounds |
| 1172 | } | 1191 | } |
| ... | @@ -1188,7 +1207,7 @@ const Parser = struct { | ... | @@ -1188,7 +1207,7 @@ const Parser = struct { |
| 1188 | if (@"union".field_types[i] == void) { | 1207 | if (@"union".field_types[i] == void) { |
| 1189 | return self.failNode(field_val, "expected type 'void'"); | 1208 | return self.failNode(field_val, "expected type 'void'"); |
| 1190 | } else { | 1209 | } else { |
| 1191 | out.* = @unionInit(@TypeOf(out.*), @"union".field_names[i], undefined); | 1210 | self.write(out, @unionInit(@TypeOf(out.*), @"union".field_names[i], undefined)); |
| 1192 | try self.parseExprInto(field_val, &@field(out.*, @"union".field_names[i])); | 1211 | try self.parseExprInto(field_val, &@field(out.*, @"union".field_names[i])); |
| 1193 | } | 1212 | } |
| 1194 | }, | 1213 | }, |
| ... | @@ -1363,6 +1382,16 @@ const Parser = struct { | ... | @@ -1363,6 +1382,16 @@ const Parser = struct { |
| 1363 | .note = null, | 1382 | .note = null, |
| 1364 | }); | 1383 | }); |
| 1365 | } | 1384 | } |
| | 1385 | |
| | 1386 | /// Write to out, freeing the old value first if necessary. |
| | 1387 | fn write(self: *@This(), out: anytype, new: @TypeOf(out.*)) void { |
| | 1388 | if (@typeInfo(@TypeOf(out)) == .pointer) { |
| | 1389 | if (self.options.free_on_write and self.pointer_depth == 0) { |
| | 1390 | free(self.gpa, out.*); |
| | 1391 | } |
| | 1392 | } |
| | 1393 | out.* = new; |
| | 1394 | } |
| 1366 | }; | 1395 | }; |
| 1367 | | 1396 | |
| 1368 | fn intFromFloatExact(T: type, value: anytype) ?T { | 1397 | fn intFromFloatExact(T: type, value: anytype) ?T { |
| ... | @@ -3785,12 +3814,8 @@ test "std.zon aligned pointers" { | ... | @@ -3785,12 +3814,8 @@ test "std.zon aligned pointers" { |
| 3785 | try std.testing.expectEqualDeep(expected.inner, found.inner); | 3814 | try std.testing.expectEqualDeep(expected.inner, found.inner); |
| 3786 | } | 3815 | } |
| 3787 | | 3816 | |
| 3788 | test "std.zon update semantics" { | 3817 | test "std.zon update" { |
| 3789 | // Test that the update logic works as expected | 3818 | const gpa = std.testing.allocator; |
| 3790 | | | |
| 3791 | var arena_allocator: std.heap.ArenaAllocator = .init(std.testing.allocator); | | |
| 3792 | defer arena_allocator.deinit(); | | |
| 3793 | const arena = arena_allocator.allocator(); | | |
| 3794 | | 3819 | |
| 3795 | const Vector = struct { x: f32, y: f32, z: f32 }; | 3820 | const Vector = struct { x: f32, y: f32, z: f32 }; |
| 3796 | const MyStruct = struct { | 3821 | const MyStruct = struct { |
| ... | @@ -3802,42 +3827,58 @@ test "std.zon update semantics" { | ... | @@ -3802,42 +3827,58 @@ test "std.zon update semantics" { |
| 3802 | }, | 3827 | }, |
| 3803 | ptr: *Vector, | 3828 | ptr: *Vector, |
| 3804 | optional: ?u32 = null, | 3829 | optional: ?u32 = null, |
| 3805 | str: []const u8 = "hello, world", | 3830 | str: []const u8, |
| 3806 | }; | 3831 | }; |
| 3807 | | 3832 | |
| 3808 | var v: Vector = .{ .x = 1, .y = 2, .z = 3 }; | | |
| 3809 | var expected: MyStruct = .{ | 3833 | var expected: MyStruct = .{ |
| 3810 | .foo = 10, | 3834 | .foo = 10, |
| 3811 | .bar = true, | 3835 | .bar = true, |
| 3812 | .baz = .{ .a = .{ 1, 2 }, .b = .c }, | 3836 | .baz = .{ .a = .{ 1, 2 }, .b = .c }, |
| 3813 | .ptr = &v, | 3837 | .ptr = b: { |
| | 3838 | const v = gpa.create(Vector) catch @panic("oom"); |
| | 3839 | v.* = .{ .x = 1, .y = 2, .z = 3 }; |
| | 3840 | break :b v; |
| | 3841 | }, |
| | 3842 | .str = gpa.dupe(u8, "hello, world") catch @panic("oom"), |
| | 3843 | }; |
| | 3844 | defer free(gpa, expected); |
| | 3845 | var found: MyStruct = .{ |
| | 3846 | .foo = 10, |
| | 3847 | .bar = true, |
| | 3848 | .baz = .{ .a = .{ 1, 2 }, .b = .c }, |
| | 3849 | .ptr = b: { |
| | 3850 | const v = gpa.create(Vector) catch @panic("oom"); |
| | 3851 | v.* = .{ .x = 1, .y = 2, .z = 3 }; |
| | 3852 | break :b v; |
| | 3853 | }, |
| | 3854 | .str = gpa.dupe(u8, "hello, world") catch @panic("oom"), |
| 3814 | }; | 3855 | }; |
| 3815 | var found = expected; | 3856 | defer free(gpa, found); |
| 3816 | | 3857 | |
| 3817 | try updateFromSliceAlloc( | 3858 | try updateFromSliceAlloc( |
| 3818 | MyStruct, | 3859 | MyStruct, |
| 3819 | arena, | 3860 | gpa, |
| 3820 | &found, | 3861 | &found, |
| 3821 | ".{}", | 3862 | ".{}", |
| 3822 | null, | 3863 | null, |
| 3823 | .{}, | 3864 | .{}, |
| 3824 | ); | 3865 | ); |
| 3825 | try std.testing.expectEqual(expected, found); | 3866 | try std.testing.expectEqualDeep(expected, found); |
| 3826 | | 3867 | |
| 3827 | try updateFromSliceAlloc( | 3868 | try updateFromSliceAlloc( |
| 3828 | MyStruct, | 3869 | MyStruct, |
| 3829 | arena, | 3870 | gpa, |
| 3830 | &found, | 3871 | &found, |
| 3831 | ".{ .bar = false }", | 3872 | ".{ .bar = false }", |
| 3832 | null, | 3873 | null, |
| 3833 | .{}, | 3874 | .{}, |
| 3834 | ); | 3875 | ); |
| 3835 | expected.bar = false; | 3876 | expected.bar = false; |
| 3836 | try std.testing.expectEqual(expected, found); | 3877 | try std.testing.expectEqualDeep(expected, found); |
| 3837 | | 3878 | |
| 3838 | try updateFromSliceAlloc( | 3879 | try updateFromSliceAlloc( |
| 3839 | MyStruct, | 3880 | MyStruct, |
| 3840 | arena, | 3881 | gpa, |
| 3841 | &found, | 3882 | &found, |
| 3842 | ".{ .baz = .{ .a = .{ 2, 4 } } }", | 3883 | ".{ .baz = .{ .a = .{ 2, 4 } } }", |
| 3843 | null, | 3884 | null, |
| ... | @@ -3845,11 +3886,11 @@ test "std.zon update semantics" { | ... | @@ -3845,11 +3886,11 @@ test "std.zon update semantics" { |
| 3845 | ); | 3886 | ); |
| 3846 | expected.baz.a[0] = 2; | 3887 | expected.baz.a[0] = 2; |
| 3847 | expected.baz.a[1] = 4; | 3888 | expected.baz.a[1] = 4; |
| 3848 | try std.testing.expectEqual(expected, found); | 3889 | try std.testing.expectEqualDeep(expected, found); |
| 3849 | | 3890 | |
| 3850 | try updateFromSliceAlloc( | 3891 | try updateFromSliceAlloc( |
| 3851 | MyStruct, | 3892 | MyStruct, |
| 3852 | arena, | 3893 | gpa, |
| 3853 | &found, | 3894 | &found, |
| 3854 | ".{ .foo = 11, .baz = .{ .b = .d } }", | 3895 | ".{ .foo = 11, .baz = .{ .b = .d } }", |
| 3855 | null, | 3896 | null, |
| ... | @@ -3857,33 +3898,33 @@ test "std.zon update semantics" { | ... | @@ -3857,33 +3898,33 @@ test "std.zon update semantics" { |
| 3857 | ); | 3898 | ); |
| 3858 | expected.foo = 11; | 3899 | expected.foo = 11; |
| 3859 | expected.baz.b = .d; | 3900 | expected.baz.b = .d; |
| 3860 | try std.testing.expectEqual(expected, found); | 3901 | try std.testing.expectEqualDeep(expected, found); |
| 3861 | | 3902 | |
| 3862 | try updateFromSliceAlloc( | 3903 | try updateFromSliceAlloc( |
| 3863 | MyStruct, | 3904 | MyStruct, |
| 3864 | arena, | 3905 | gpa, |
| 3865 | &found, | 3906 | &found, |
| 3866 | ".{ .optional = 10 }", | 3907 | ".{ .optional = 10 }", |
| 3867 | null, | 3908 | null, |
| 3868 | .{}, | 3909 | .{}, |
| 3869 | ); | 3910 | ); |
| 3870 | expected.optional = 10; | 3911 | expected.optional = 10; |
| 3871 | try std.testing.expectEqual(expected, found); | 3912 | try std.testing.expectEqualDeep(expected, found); |
| 3872 | | 3913 | |
| 3873 | try updateFromSliceAlloc( | 3914 | try updateFromSliceAlloc( |
| 3874 | MyStruct, | 3915 | MyStruct, |
| 3875 | arena, | 3916 | gpa, |
| 3876 | &found, | 3917 | &found, |
| 3877 | ".{ .optional = null }", | 3918 | ".{ .optional = null }", |
| 3878 | null, | 3919 | null, |
| 3879 | .{}, | 3920 | .{}, |
| 3880 | ); | 3921 | ); |
| 3881 | expected.optional = null; | 3922 | expected.optional = null; |
| 3882 | try std.testing.expectEqual(expected, found); | 3923 | try std.testing.expectEqualDeep(expected, found); |
| 3883 | | 3924 | |
| 3884 | try updateFromSliceAlloc( | 3925 | try updateFromSliceAlloc( |
| 3885 | MyStruct, | 3926 | MyStruct, |
| 3886 | arena, | 3927 | gpa, |
| 3887 | &found, | 3928 | &found, |
| 3888 | ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }", | 3929 | ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }", |
| 3889 | null, | 3930 | null, |
| ... | @@ -3896,13 +3937,14 @@ test "std.zon update semantics" { | ... | @@ -3896,13 +3937,14 @@ test "std.zon update semantics" { |
| 3896 | | 3937 | |
| 3897 | try updateFromSliceAlloc( | 3938 | try updateFromSliceAlloc( |
| 3898 | MyStruct, | 3939 | MyStruct, |
| 3899 | arena, | 3940 | gpa, |
| 3900 | &found, | 3941 | &found, |
| 3901 | ".{ .str = \"foo\" }", | 3942 | ".{ .str = \"foo\" }", |
| 3902 | null, | 3943 | null, |
| 3903 | .{}, | 3944 | .{}, |
| 3904 | ); | 3945 | ); |
| 3905 | expected.str = "foo"; | 3946 | gpa.free(expected.str); |
| | 3947 | expected.str = gpa.dupe(u8, "foo") catch @panic("oom"); |
| 3906 | try std.testing.expectEqualDeep(expected, found); | 3948 | try std.testing.expectEqualDeep(expected, found); |
| 3907 | } | 3949 | } |
| 3908 | | 3950 | |
| ... | @@ -3910,9 +3952,7 @@ test "std.zon variants" { | ... | @@ -3910,9 +3952,7 @@ test "std.zon variants" { |
| 3910 | // Just a smoke test, we don't need to test each variant thoroughly because they all call into | 3952 | // Just a smoke test, we don't need to test each variant thoroughly because they all call into |
| 3911 | // the same code. | 3953 | // the same code. |
| 3912 | | 3954 | |
| 3913 | var arena_allocator: std.heap.ArenaAllocator = .init(std.testing.allocator); | 3955 | const gpa = std.testing.allocator; |
| 3914 | defer arena_allocator.deinit(); | | |
| 3915 | const arena = arena_allocator.allocator(); | | |
| 3916 | | 3956 | |
| 3917 | const Struct = struct { a: u32, b: u32 }; | 3957 | const Struct = struct { a: u32, b: u32 }; |
| 3918 | const start: Struct = .{ .a = 10, .b = 20 }; | 3958 | const start: Struct = .{ .a = 10, .b = 20 }; |
| ... | @@ -3920,15 +3960,17 @@ test "std.zon variants" { | ... | @@ -3920,15 +3960,17 @@ test "std.zon variants" { |
| 3920 | | 3960 | |
| 3921 | // Update | 3961 | // Update |
| 3922 | { | 3962 | { |
| 3923 | const ast = try std.zig.Ast.parse(arena, ".{ .a = 100 }", .{ .mode = .zon }); | 3963 | var ast = try std.zig.Ast.parse(gpa, ".{ .a = 100 }", .{ .mode = .zon }); |
| 3924 | const zoir = try ZonGen.generate(arena, ast, .{ .parse_str_lits = false }); | 3964 | defer ast.deinit(gpa); |
| | 3965 | const zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false }); |
| | 3966 | defer zoir.deinit(gpa); |
| 3925 | | 3967 | |
| 3926 | var curr = start; | 3968 | var curr = start; |
| 3927 | try updateFromSlice(Struct, arena, &curr, ".{ .a = 100 }", null, .{}); | 3969 | try updateFromSlice(Struct, gpa, &curr, ".{ .a = 100 }", null, .{}); |
| 3928 | try std.testing.expectEqual(end, curr); | 3970 | try std.testing.expectEqual(end, curr); |
| 3929 | | 3971 | |
| 3930 | curr = start; | 3972 | curr = start; |
| 3931 | try updateFromSliceAlloc(Struct, arena, &curr, ".{ .a = 100 }", null, .{}); | 3973 | try updateFromSliceAlloc(Struct, gpa, &curr, ".{ .a = 100 }", null, .{}); |
| 3932 | try std.testing.expectEqual(end, curr); | 3974 | try std.testing.expectEqual(end, curr); |
| 3933 | | 3975 | |
| 3934 | curr = start; | 3976 | curr = start; |
| ... | @@ -3936,7 +3978,7 @@ test "std.zon variants" { | ... | @@ -3936,7 +3978,7 @@ test "std.zon variants" { |
| 3936 | try std.testing.expectEqual(end, curr); | 3978 | try std.testing.expectEqual(end, curr); |
| 3937 | | 3979 | |
| 3938 | curr = start; | 3980 | curr = start; |
| 3939 | try updateFromZoirAlloc(Struct, arena, &curr, ast, zoir, null, .{}); | 3981 | try updateFromZoirAlloc(Struct, gpa, &curr, ast, zoir, null, .{}); |
| 3940 | try std.testing.expectEqual(end, curr); | 3982 | try std.testing.expectEqual(end, curr); |
| 3941 | | 3983 | |
| 3942 | curr = start; | 3984 | curr = start; |
| ... | @@ -3944,29 +3986,31 @@ test "std.zon variants" { | ... | @@ -3944,29 +3986,31 @@ test "std.zon variants" { |
| 3944 | try std.testing.expectEqual(end, curr); | 3986 | try std.testing.expectEqual(end, curr); |
| 3945 | | 3987 | |
| 3946 | curr = start; | 3988 | curr = start; |
| 3947 | try updateFromZoirNodeAlloc(Struct, arena, &curr, ast, zoir, .root, null, .{}); | 3989 | try updateFromZoirNodeAlloc(Struct, gpa, &curr, ast, zoir, .root, null, .{}); |
| 3948 | try std.testing.expectEqual(end, curr); | 3990 | try std.testing.expectEqual(end, curr); |
| 3949 | } | 3991 | } |
| 3950 | | 3992 | |
| 3951 | // From | 3993 | // From |
| 3952 | { | 3994 | { |
| 3953 | const ast = try std.zig.Ast.parse(arena, ".{ .a = 100, .b = 20 }", .{ .mode = .zon }); | 3995 | var ast = try std.zig.Ast.parse(gpa, ".{ .a = 100, .b = 20 }", .{ .mode = .zon }); |
| 3954 | const zoir = try ZonGen.generate(arena, ast, .{ .parse_str_lits = false }); | 3996 | defer ast.deinit(gpa); |
| | 3997 | const zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false }); |
| | 3998 | defer zoir.deinit(gpa); |
| 3955 | | 3999 | |
| 3956 | try std.testing.expectEqual( | 4000 | try std.testing.expectEqual( |
| 3957 | end, | 4001 | end, |
| 3958 | try fromSlice(Struct, arena, ".{ .a = 100, .b = 20 }", null, .{}), | 4002 | try fromSlice(Struct, gpa, ".{ .a = 100, .b = 20 }", null, .{}), |
| 3959 | ); | 4003 | ); |
| 3960 | try std.testing.expectEqual( | 4004 | try std.testing.expectEqual( |
| 3961 | end, | 4005 | end, |
| 3962 | try fromSliceAlloc(Struct, arena, ".{ .a = 100, .b = 20 }", null, .{}), | 4006 | try fromSliceAlloc(Struct, gpa, ".{ .a = 100, .b = 20 }", null, .{}), |
| 3963 | ); | 4007 | ); |
| 3964 | try std.testing.expectEqual( | 4008 | try std.testing.expectEqual( |
| 3965 | try fromZoir(Struct, ast, zoir, null, .{}), | 4009 | try fromZoir(Struct, ast, zoir, null, .{}), |
| 3966 | end, | 4010 | end, |
| 3967 | ); | 4011 | ); |
| 3968 | try std.testing.expectEqual( | 4012 | try std.testing.expectEqual( |
| 3969 | try fromZoirAlloc(Struct, arena, ast, zoir, null, .{}), | 4013 | try fromZoirAlloc(Struct, gpa, ast, zoir, null, .{}), |
| 3970 | end, | 4014 | end, |
| 3971 | ); | 4015 | ); |
| 3972 | try std.testing.expectEqual( | 4016 | try std.testing.expectEqual( |
| ... | @@ -3974,7 +4018,7 @@ test "std.zon variants" { | ... | @@ -3974,7 +4018,7 @@ test "std.zon variants" { |
| 3974 | end, | 4018 | end, |
| 3975 | ); | 4019 | ); |
| 3976 | try std.testing.expectEqual( | 4020 | try std.testing.expectEqual( |
| 3977 | try fromZoirNodeAlloc(Struct, arena, ast, zoir, .root, null, .{}), | 4021 | try fromZoirNodeAlloc(Struct, gpa, ast, zoir, .root, null, .{}), |
| 3978 | end, | 4022 | end, |
| 3979 | ); | 4023 | ); |
| 3980 | } | 4024 | } |