authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-07-18 21:39:17-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-09-26 12:35:38-07:00
log07149649ce9201399233628d2dea61ebb061c430
tree7e9877f816cb20eb766b3f3edd8c85a593f00caa
parent9e87e807ab65449845d12eaa3d98e2792194354d

Accept options structs instead of args

I wrote this API, and even I can't remember what order the arguments are in. Furthermore, the types won't be enough to distinguish between them when I add an arena alongside the GPA in a followup.

1 files changed, 1298 insertions(+), 615 deletions(-)

lib/std/zon/parse.zig+1298-615
......@@ -24,47 +24,6 @@ const ArrayList = std.ArrayList;
2424/// Rename when adding or removing support for a type.
2525const valid_types = {};
2626
27/// Deprecated.
28pub const Options = FromOptions;
29
30/// Configuration for the `from*` functions.
31pub const FromOptions = struct {
32 /// If true, unknown fields do not error.
33 ignore_unknown_fields: bool = false,
34 /// If true, the parser cleans up partially parsed values on error. This requires some extra
35 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
36 /// you're using arena allocation.)
37 free_on_error: bool = true,
38
39 fn toParserOptions(self: FromOptions) Parser.Options {
40 return .{
41 .ignore_unknown_fields = self.ignore_unknown_fields,
42 .ignore_missing_fields = false,
43 .free_on_error = self.free_on_error,
44 .free_on_write = false,
45 };
46 }
47};
48
49/// Configuration for the `updateFrom*` variants.
50pub const UpdateFromOptions = struct {
51 /// If true, unknown fields do not error.
52 ignore_unknown_fields: bool = false,
53 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
54 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
55 /// In this case, you can use arena allocation.
56 free_on_write: bool = true,
57
58 fn toParserOptions(self: UpdateFromOptions) Parser.Options {
59 return .{
60 .ignore_unknown_fields = self.ignore_unknown_fields,
61 .ignore_missing_fields = true,
62 .free_on_error = false,
63 .free_on_write = true,
64 };
65 }
66};
67
6827pub const Error = union(enum) {
6928 zoir: Zoir.CompileError,
7029 type_check: Error.TypeCheckFailure,
......@@ -279,6 +238,19 @@ pub const Diagnostics = struct {
279238 }
280239};
281240
241pub const FromSliceOptions = struct {
242 gpa: Allocator,
243 source: [:0]const u8,
244 /// Write human readable error messages here.
245 diag: ?*Diagnostics,
246 /// If true, unknown fields do not error.
247 ignore_unknown_fields: bool = false,
248 /// If true, the parser cleans up partially parsed values on error. This requires some extra
249 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
250 /// you're using arena allocation.)
251 free_on_error: bool = true,
252};
253
282254/// Parses the given slice as ZON.
283255///
284256/// Returns `error.OutOfMemory` on allocation failure, or `error.ParseZon` error if the ZON is
......@@ -291,15 +263,27 @@ pub const Diagnostics = struct {
291263/// doesn't need to be freed.
292264///
293265/// An allocator is still required for temporary allocations made during parsing.
294pub fn fromSlice(
295 T: type,
296 gpa: Allocator,
297 source: [:0]const u8,
298 diag: ?*Diagnostics,
299 options: FromOptions,
300) error{ OutOfMemory, ParseZon }!T {
266pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
301267 comptime assert(!requiresAllocator(T));
302 return fromSliceAlloc(T, gpa, source, diag, options);
268 return fromSliceAlloc(T, options);
269}
270
271pub fn UpdateFromSliceOptions(T: type) type {
272 return struct {
273 gpa: Allocator,
274 /// The value to update.
275 value: *T,
276 /// The ZON source.
277 source: [:0]const u8,
278 /// Write human readable error messages here.
279 diag: ?*Diagnostics,
280 /// If true, unknown fields do not error.
281 ignore_unknown_fields: bool = false,
282 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
283 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
284 /// In this case, you can use arena allocation.
285 free_on_write: bool = true,
286 };
303287}
304288
305289/// Similar to `fromSlice`, but updates an existing value `current`. Fields not specified by ZON are
......@@ -307,45 +291,52 @@ pub fn fromSlice(
307291/// failure, values that were updated prior to the failure are left updated.
308292pub fn updateFromSlice(
309293 T: type,
310 gpa: Allocator,
311 current: *T,
312 source: [:0]const u8,
313 diag: ?*Diagnostics,
314 options: UpdateFromOptions,
294 options: UpdateFromSliceOptions(T),
315295) error{ OutOfMemory, ParseZon }!void {
316296 comptime assert(!requiresAllocator(T));
317 try updateFromSliceAlloc(T, gpa, current, source, diag, options);
297 try updateFromSliceAlloc(T, options);
318298}
319299
300pub const FromSliceAllocOptions = FromSliceOptions;
301
320302/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see
321303/// `free`.
322pub fn fromSliceAlloc(
323 T: type,
324 gpa: Allocator,
325 source: [:0]const u8,
326 diag: ?*Diagnostics,
327 options: FromOptions,
328) error{ OutOfMemory, ParseZon }!T {
304pub fn fromSliceAlloc(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
329305 var result: T = undefined;
330 try parseSliceAlloc(T, &result, gpa, source, diag, options.toParserOptions());
306 try parseSliceAlloc(T, &result, options.gpa, options.source, options.diag, .{
307 .ignore_unknown_fields = options.ignore_unknown_fields,
308 .ignore_missing_fields = false,
309 .free_on_error = options.free_on_error,
310 .free_on_write = false,
311 });
331312 return result;
332313}
333314
315pub const UpdateFromSliceAllocOptions = UpdateFromSliceOptions;
316
334317/// Like updateFromSlice`, but the result may contain pointers.
335318pub fn updateFromSliceAlloc(
336319 T: type,
337 gpa: Allocator,
338 current: *T,
339 source: [:0]const u8,
340 diag: ?*Diagnostics,
341 options: UpdateFromOptions,
320 options: UpdateFromSliceAllocOptions(T),
342321) error{ OutOfMemory, ParseZon }!void {
343 try parseSliceAlloc(T, current, gpa, source, diag, options.toParserOptions());
322 try parseSliceAlloc(
323 T,
324 options.value,
325 options.gpa,
326 options.source,
327 options.diag,
328 .{
329 .ignore_unknown_fields = options.ignore_unknown_fields,
330 .ignore_missing_fields = true,
331 .free_on_error = false,
332 .free_on_write = options.free_on_write,
333 },
334 );
344335}
345336
346337fn parseSliceAlloc(
347338 T: type,
348 current: *T,
339 out: *T,
349340 gpa: Allocator,
350341 source: [:0]const u8,
351342 diag: ?*Diagnostics,
......@@ -363,92 +354,167 @@ fn parseSliceAlloc(
363354 defer if (diag == null) zoir.deinit(gpa);
364355
365356 if (diag) |s| s.* = .{};
366 try parseZoirAlloc(T, gpa, current, ast, zoir, .root, diag, options);
357 try parseZoirAlloc(T, out, gpa, ast, zoir, .root, diag, options);
367358}
368359
369/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
370pub fn fromZoir(
371 T: type,
360pub const FromZoirOptions = struct {
361 /// The AST for this this ZON value.
372362 ast: Ast,
363 /// The zig object intermediate representation of this ZON value.
373364 zoir: Zoir,
374 node: Zoir.Node.Index,
365 /// The node to start parsing at.
366 node: Zoir.Node.Index = .root,
367 /// Write human readable error messages here.
375368 diag: ?*Diagnostics,
376 options: FromOptions,
377) error{ParseZon}!T {
369 /// If true, unknown fields do not error.
370 ignore_unknown_fields: bool = false,
371 /// If true, the parser cleans up partially parsed values on error. This requires some extra
372 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
373 /// you're using arena allocation.)
374 free_on_error: bool = true,
375};
376
377/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
378pub fn fromZoir(T: type, options: FromZoirOptions) error{ParseZon}!T {
378379 comptime assert(!requiresAllocator(T));
379 return fromZoirAlloc(
380 T,
381 .failing,
382 ast,
383 zoir,
384 node,
385 diag,
386 options,
387 ) catch |err| switch (err) {
380 return fromZoirAlloc(T, .{
381 .gpa = .failing,
382 .ast = options.ast,
383 .zoir = options.zoir,
384 .node = options.node,
385 .diag = options.diag,
386 .ignore_unknown_fields = options.ignore_unknown_fields,
387 .free_on_error = options.free_on_error,
388 }) catch |err| switch (err) {
388389 error.OutOfMemory => unreachable, // Checked by comptime assertion above
389390 else => |e| return e,
390391 };
391392}
392393
394pub fn UpdateFromZoirOptions(T: type) type {
395 return struct {
396 value: *T,
397 /// The AST for this ZON value.
398 ast: Ast,
399 /// The zig object intermediate representation of this ZON value.
400 zoir: Zoir,
401 /// The node to start parsing at.
402 node: Zoir.Node.Index = .root,
403 /// Write human readable error messages here.
404 diag: ?*Diagnostics,
405 /// If true, unknown fields do not error.
406 ignore_unknown_fields: bool = false,
407 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
408 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
409 /// In this case, you can use arena allocation.
410 free_on_write: bool = true,
411 };
412}
413
393414/// Like `updateSlice`, but operates on `Zoir` instead of ZON source.
394415pub fn updateFromZoir(
395416 T: type,
396 current: *T,
397 ast: Ast,
398 zoir: Zoir,
399 node: Zoir.Node.Index,
400 diag: ?*Diagnostics,
401 options: UpdateFromOptions,
417 options: UpdateFromZoirOptions(T),
402418) error{ParseZon}!void {
403419 comptime assert(!requiresAllocator(T));
404 updateFromZoirAlloc(
405 T,
406 .failing,
407 current,
408 ast,
409 zoir,
410 node,
411 diag,
412 options,
413 ) catch |err| switch (err) {
420 updateFromZoirAlloc(T, .{
421 .gpa = .failing,
422 .value = options.value,
423 .ast = options.ast,
424 .zoir = options.zoir,
425 .node = options.node,
426 .diag = options.diag,
427 .ignore_unknown_fields = options.ignore_unknown_fields,
428 .free_on_write = options.free_on_write,
429 }) catch |err| switch (err) {
414430 error.OutOfMemory => unreachable, // Checked by comptime assertion above
415431 else => |e| return e,
416432 };
417433}
418434
419/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
420pub fn fromZoirAlloc(
421 T: type,
435pub const FromZoirAllocOptions = struct {
422436 gpa: Allocator,
437 /// The AST for this ZON value.
423438 ast: Ast,
439 /// The zig object intermediate representation of this ZON value.
424440 zoir: Zoir,
425 node: Zoir.Node.Index,
441 /// The node to start parsing at.
442 node: Zoir.Node.Index = .root,
443 /// Write human readable error messages here.
426444 diag: ?*Diagnostics,
427 options: FromOptions,
428) error{ OutOfMemory, ParseZon }!T {
445 /// If true, unknown fields do not error.
446 ignore_unknown_fields: bool = false,
447 /// If true, the parser cleans up partially parsed values on error. This requires some extra
448 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
449 /// you're using arena allocation.)
450 free_on_error: bool = true,
451};
452
453/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
454pub fn fromZoirAlloc(T: type, options: FromZoirAllocOptions) error{ OutOfMemory, ParseZon }!T {
429455 var out: T = undefined;
430 try parseZoirAlloc(T, gpa, &out, ast, zoir, node, diag, options.toParserOptions());
456 try parseZoirAlloc(
457 T,
458 &out,
459 options.gpa,
460 options.ast,
461 options.zoir,
462 options.node,
463 options.diag,
464 .{
465 .ignore_unknown_fields = options.ignore_unknown_fields,
466 .ignore_missing_fields = false,
467 .free_on_error = options.free_on_error,
468 .free_on_write = false,
469 },
470 );
431471 return out;
432472}
433473
474pub fn UpdateFromZoirAllocOptions(T: type) type {
475 return struct {
476 gpa: Allocator,
477 value: *T,
478 ast: Ast,
479 zoir: Zoir,
480 node: Zoir.Node.Index = .root,
481 /// Write human readable error messages here.
482 diag: ?*Diagnostics,
483 /// If true, unknown fields do not error.
484 ignore_unknown_fields: bool = false,
485 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
486 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
487 /// In this case, you can use arena allocation.
488 free_on_write: bool = true,
489 };
490}
491
434492/// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source.
435493pub fn updateFromZoirAlloc(
436494 T: type,
437 gpa: Allocator,
438 current: *T,
439 ast: Ast,
440 zoir: Zoir,
441 node: Zoir.Node.Index,
442 diag: ?*Diagnostics,
443 options: UpdateFromOptions,
495 options: UpdateFromZoirAllocOptions(T),
444496) error{ OutOfMemory, ParseZon }!void {
445 return parseZoirAlloc(T, gpa, current, ast, zoir, node, diag, options.toParserOptions());
497 return parseZoirAlloc(
498 T,
499 options.value,
500 options.gpa,
501 options.ast,
502 options.zoir,
503 options.node,
504 options.diag,
505 .{
506 .ignore_unknown_fields = options.ignore_unknown_fields,
507 .ignore_missing_fields = true,
508 .free_on_error = false,
509 .free_on_write = options.free_on_write,
510 },
511 );
446512}
447513
448514fn parseZoirAlloc(
449515 T: type,
450 gpa: Allocator,
451516 out: *T,
517 gpa: Allocator,
452518 ast: Ast,
453519 zoir: Zoir,
454520 node: Zoir.Node.Index,
......@@ -1449,7 +1515,7 @@ test "std.zon ast errors" {
14491515 defer diag.deinit(gpa);
14501516 try std.testing.expectError(
14511517 error.ParseZon,
1452 fromSlice(struct {}, gpa, ".{.x = 1 .y = 2}", &diag, .{}),
1518 fromSlice(struct {}, .{ .gpa = gpa, .source = ".{.x = 1 .y = 2}", .diag = &diag }),
14531519 );
14541520 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{diag});
14551521}
......@@ -1457,20 +1523,28 @@ test "std.zon ast errors" {
14571523test "std.zon comments" {
14581524 const gpa = std.testing.allocator;
14591525
1460 try std.testing.expectEqual(@as(u8, 10), fromSlice(u8, gpa,
1526 try std.testing.expectEqual(@as(u8, 10), fromSlice(u8, .{
1527 .gpa = gpa,
1528 .source =
14611529 \\// comment
14621530 \\10 // comment
14631531 \\// comment
1464 , null, .{}));
1532 ,
1533 .diag = null,
1534 }));
14651535
14661536 {
14671537 var diag: Diagnostics = .{};
14681538 defer diag.deinit(gpa);
1469 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa,
1539 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
1540 .gpa = gpa,
1541 .source =
14701542 \\//! comment
14711543 \\10 // comment
14721544 \\// comment
1473 , &diag, .{}));
1545 ,
1546 .diag = &diag,
1547 }));
14741548 try std.testing.expectFmt(
14751549 "1:1: error: expected expression, found 'a document comment'\n",
14761550 "{f}",
......@@ -1481,26 +1555,24 @@ test "std.zon comments" {
14811555
14821556test "std.zon failure/oom formatting" {
14831557 const gpa = std.testing.allocator;
1484 var failing_allocator = std.testing.FailingAllocator.init(gpa, .{
1485 .fail_index = 0,
1486 .resize_fail_index = 0,
1487 });
14881558 var diag: Diagnostics = .{};
14891559 defer diag.deinit(gpa);
1490 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc(
1491 []const u8,
1492 failing_allocator.allocator(),
1493 "\"foo\"",
1494 &diag,
1495 .{},
1496 ));
1560 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc([]const u8, .{
1561 .gpa = .failing,
1562 .source = "\"foo\"",
1563 .diag = &diag,
1564 }));
14971565 try std.testing.expectFmt("", "{f}", .{diag});
14981566}
14991567
15001568test "std.zon fromSliceAlloc syntax error" {
15011569 try std.testing.expectError(
15021570 error.ParseZon,
1503 fromSlice(u8, std.testing.allocator, ".{", null, .{}),
1571 fromSlice(u8, .{
1572 .gpa = std.testing.allocator,
1573 .source = ".{",
1574 .diag = null,
1575 }),
15041576 );
15051577}
15061578
......@@ -1509,17 +1581,33 @@ test "std.zon optional" {
15091581
15101582 // Basic usage
15111583 {
1512 const none = try fromSlice(?u32, gpa, "null", null, .{});
1584 const none = try fromSlice(?u32, .{
1585 .gpa = gpa,
1586 .source = "null",
1587 .diag = null,
1588 });
15131589 try std.testing.expect(none == null);
1514 const some = try fromSlice(?u32, gpa, "1", null, .{});
1590 const some = try fromSlice(?u32, .{
1591 .gpa = gpa,
1592 .source = "1",
1593 .diag = null,
1594 });
15151595 try std.testing.expect(some.? == 1);
15161596 }
15171597
15181598 // Deep free
15191599 {
1520 const none = try fromSliceAlloc(?[]const u8, gpa, "null", null, .{});
1600 const none = try fromSliceAlloc(?[]const u8, .{
1601 .gpa = gpa,
1602 .source = "null",
1603 .diag = null,
1604 });
15211605 try std.testing.expect(none == null);
1522 const some = try fromSliceAlloc(?[]const u8, gpa, "\"foo\"", null, .{});
1606 const some = try fromSliceAlloc(?[]const u8, .{
1607 .gpa = gpa,
1608 .source = "\"foo\"",
1609 .diag = null,
1610 });
15231611 defer free(gpa, some);
15241612 try std.testing.expectEqualStrings("foo", some.?);
15251613 }
......@@ -1533,18 +1621,42 @@ test "std.zon unions" {
15331621 const Tagged = union(enum) { x: f32, @"y y": bool, z, @"z z" };
15341622 const Untagged = union { x: f32, @"y y": bool, z: void, @"z z": void };
15351623
1536 const tagged_x = try fromSlice(Tagged, gpa, ".{.x = 1.5}", null, .{});
1624 const tagged_x = try fromSlice(Tagged, .{
1625 .gpa = gpa,
1626 .source = ".{.x = 1.5}",
1627 .diag = null,
1628 });
15371629 try std.testing.expectEqual(Tagged{ .x = 1.5 }, tagged_x);
1538 const tagged_y = try fromSlice(Tagged, gpa, ".{.@\"y y\" = true}", null, .{});
1630 const tagged_y = try fromSlice(Tagged, .{
1631 .gpa = gpa,
1632 .source = ".{.@\"y y\" = true}",
1633 .diag = null,
1634 });
15391635 try std.testing.expectEqual(Tagged{ .@"y y" = true }, tagged_y);
1540 const tagged_z_shorthand = try fromSlice(Tagged, gpa, ".z", null, .{});
1636 const tagged_z_shorthand = try fromSlice(Tagged, .{
1637 .gpa = gpa,
1638 .source = ".z",
1639 .diag = null,
1640 });
15411641 try std.testing.expectEqual(@as(Tagged, .z), tagged_z_shorthand);
1542 const tagged_zz_shorthand = try fromSlice(Tagged, gpa, ".@\"z z\"", null, .{});
1642 const tagged_zz_shorthand = try fromSlice(Tagged, .{
1643 .gpa = gpa,
1644 .source = ".@\"z z\"",
1645 .diag = null,
1646 });
15431647 try std.testing.expectEqual(@as(Tagged, .@"z z"), tagged_zz_shorthand);
15441648
1545 const untagged_x = try fromSlice(Untagged, gpa, ".{.x = 1.5}", null, .{});
1649 const untagged_x = try fromSlice(Untagged, .{
1650 .gpa = gpa,
1651 .source = ".{.x = 1.5}",
1652 .diag = null,
1653 });
15461654 try std.testing.expect(untagged_x.x == 1.5);
1547 const untagged_y = try fromSlice(Untagged, gpa, ".{.@\"y y\" = true}", null, .{});
1655 const untagged_y = try fromSlice(Untagged, .{
1656 .gpa = gpa,
1657 .source = ".{.@\"y y\" = true}",
1658 .diag = null,
1659 });
15481660 try std.testing.expect(untagged_y.@"y y");
15491661 }
15501662
......@@ -1552,10 +1664,18 @@ test "std.zon unions" {
15521664 {
15531665 const Union = union(enum) { bar: []const u8, baz: bool };
15541666
1555 const noalloc = try fromSliceAlloc(Union, gpa, ".{.baz = false}", null, .{});
1667 const noalloc = try fromSliceAlloc(Union, .{
1668 .gpa = gpa,
1669 .source = ".{.baz = false}",
1670 .diag = null,
1671 });
15561672 try std.testing.expectEqual(Union{ .baz = false }, noalloc);
15571673
1558 const alloc = try fromSliceAlloc(Union, gpa, ".{.bar = \"qux\"}", null, .{});
1674 const alloc = try fromSliceAlloc(Union, .{
1675 .gpa = gpa,
1676 .source = ".{.bar = \"qux\"}",
1677 .diag = null,
1678 });
15591679 defer free(gpa, alloc);
15601680 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);
15611681 }
......@@ -1567,7 +1687,7 @@ test "std.zon unions" {
15671687 defer diag.deinit(gpa);
15681688 try std.testing.expectError(
15691689 error.ParseZon,
1570 fromSliceAlloc(Union, gpa, ".{.z=2.5}", &diag, .{}),
1690 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{.z=2.5}", .diag = &diag }),
15711691 );
15721692 try std.testing.expectFmt(
15731693 \\1:4: error: unexpected field 'z'
......@@ -1586,7 +1706,7 @@ test "std.zon unions" {
15861706 defer diag.deinit(gpa);
15871707 try std.testing.expectError(
15881708 error.ParseZon,
1589 fromSliceAlloc(Union, gpa, ".{.x=1}", &diag, .{}),
1709 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{.x=1}", .diag = &diag }),
15901710 );
15911711 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
15921712 }
......@@ -1598,7 +1718,11 @@ test "std.zon unions" {
15981718 defer diag.deinit(gpa);
15991719 try std.testing.expectError(
16001720 error.ParseZon,
1601 fromSliceAlloc(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
1721 fromSliceAlloc(Union, .{
1722 .gpa = gpa,
1723 .source = ".{.x = 1.5, .y = true}",
1724 .diag = &diag,
1725 }),
16021726 );
16031727 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
16041728 }
......@@ -1610,7 +1734,7 @@ test "std.zon unions" {
16101734 defer diag.deinit(gpa);
16111735 try std.testing.expectError(
16121736 error.ParseZon,
1613 fromSliceAlloc(Union, gpa, ".{}", &diag, .{}),
1737 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{}", .diag = &diag }),
16141738 );
16151739 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
16161740 }
......@@ -1620,7 +1744,11 @@ test "std.zon unions" {
16201744 const Union = union { x: void };
16211745 var diag: Diagnostics = .{};
16221746 defer diag.deinit(gpa);
1623 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".x", &diag, .{}));
1747 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1748 .gpa = gpa,
1749 .source = ".x",
1750 .diag = &diag,
1751 }));
16241752 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
16251753 }
16261754
......@@ -1629,7 +1757,11 @@ test "std.zon unions" {
16291757 const Union = union(enum) { x: void };
16301758 var diag: Diagnostics = .{};
16311759 defer diag.deinit(gpa);
1632 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".y", &diag, .{}));
1760 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1761 .gpa = gpa,
1762 .source = ".y",
1763 .diag = &diag,
1764 }));
16331765 try std.testing.expectFmt(
16341766 \\1:2: error: unexpected field 'y'
16351767 \\1:2: note: supported: 'x'
......@@ -1645,7 +1777,11 @@ test "std.zon unions" {
16451777 const Union = union(enum) { x: f32 };
16461778 var diag: Diagnostics = .{};
16471779 defer diag.deinit(gpa);
1648 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".x", &diag, .{}));
1780 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1781 .gpa = gpa,
1782 .source = ".x",
1783 .diag = &diag,
1784 }));
16491785 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
16501786 }
16511787}
......@@ -1660,16 +1796,32 @@ test "std.zon structs" {
16601796 const Vec2 = struct { x: f32, y: f32 };
16611797 const Vec3 = struct { x: f32, y: f32, z: f32 };
16621798
1663 const zero = try fromSlice(Vec0, gpa, ".{}", null, .{});
1799 const zero = try fromSlice(Vec0, .{
1800 .gpa = gpa,
1801 .source = ".{}",
1802 .diag = null,
1803 });
16641804 try std.testing.expectEqual(Vec0{}, zero);
16651805
1666 const one = try fromSlice(Vec1, gpa, ".{.x = 1.2}", null, .{});
1806 const one = try fromSlice(Vec1, .{
1807 .gpa = gpa,
1808 .source = ".{.x = 1.2}",
1809 .diag = null,
1810 });
16671811 try std.testing.expectEqual(Vec1{ .x = 1.2 }, one);
16681812
1669 const two = try fromSlice(Vec2, gpa, ".{.x = 1.2, .y = 3.4}", null, .{});
1813 const two = try fromSlice(Vec2, .{
1814 .gpa = gpa,
1815 .source = ".{.x = 1.2, .y = 3.4}",
1816 .diag = null,
1817 });
16701818 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 3.4 }, two);
16711819
1672 const three = try fromSlice(Vec3, gpa, ".{.x = 1.2, .y = 3.4, .z = 5.6}", null, .{});
1820 const three = try fromSlice(Vec3, .{
1821 .gpa = gpa,
1822 .source = ".{.x = 1.2, .y = 3.4, .z = 5.6}",
1823 .diag = null,
1824 });
16731825 try std.testing.expectEqual(Vec3{ .x = 1.2, .y = 3.4, .z = 5.6 }, three);
16741826 }
16751827
......@@ -1677,13 +1829,11 @@ test "std.zon structs" {
16771829 {
16781830 const Foo = struct { bar: []const u8, baz: []const []const u8 };
16791831
1680 const parsed = try fromSliceAlloc(
1681 Foo,
1682 gpa,
1683 ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
1684 null,
1685 .{},
1686 );
1832 const parsed = try fromSliceAlloc(Foo, .{
1833 .gpa = gpa,
1834 .source = ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
1835 .diag = null,
1836 });
16871837 defer free(gpa, parsed);
16881838 try std.testing.expectEqualDeep(Foo{ .bar = "qux", .baz = &.{ "a", "b" } }, parsed);
16891839 }
......@@ -1695,7 +1845,7 @@ test "std.zon structs" {
16951845 defer diag.deinit(gpa);
16961846 try std.testing.expectError(
16971847 error.ParseZon,
1698 fromSlice(Vec2, gpa, ".{.x=1.5, .z=2.5}", &diag, .{}),
1848 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .z=2.5}", .diag = &diag }),
16991849 );
17001850 try std.testing.expectFmt(
17011851 \\1:12: error: unexpected field 'z'
......@@ -1714,7 +1864,7 @@ test "std.zon structs" {
17141864 defer diag.deinit(gpa);
17151865 try std.testing.expectError(
17161866 error.ParseZon,
1717 fromSlice(Vec2, gpa, ".{.x=1.5, .x=2.5, .x=3.5}", &diag, .{}),
1867 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .x=2.5, .x=3.5}", .diag = &diag }),
17181868 );
17191869 try std.testing.expectFmt(
17201870 \\1:4: error: duplicate struct field name
......@@ -1726,8 +1876,11 @@ test "std.zon structs" {
17261876 // Ignore unknown fields
17271877 {
17281878 const Vec2 = struct { x: f32, y: f32 = 2.0 };
1729 const parsed = try fromSlice(Vec2, gpa, ".{ .x = 1.0, .z = 3.0 }", null, .{
1879 const parsed = try fromSlice(Vec2, .{
1880 .gpa = gpa,
1881 .source = ".{ .x = 1.0, .z = 3.0 }",
17301882 .ignore_unknown_fields = true,
1883 .diag = null,
17311884 });
17321885 try std.testing.expectEqual(Vec2{ .x = 1.0, .y = 2.0 }, parsed);
17331886 }
......@@ -1739,7 +1892,7 @@ test "std.zon structs" {
17391892 defer diag.deinit(gpa);
17401893 try std.testing.expectError(
17411894 error.ParseZon,
1742 fromSlice(Vec2, gpa, ".{.x=1.5, .z=2.5}", &diag, .{}),
1895 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .z=2.5}", .diag = &diag }),
17431896 );
17441897 try std.testing.expectFmt(
17451898 \\1:4: error: unexpected field 'x'
......@@ -1755,7 +1908,7 @@ test "std.zon structs" {
17551908 defer diag.deinit(gpa);
17561909 try std.testing.expectError(
17571910 error.ParseZon,
1758 fromSlice(Vec2, gpa, ".{.x=1.5}", &diag, .{}),
1911 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5}", .diag = &diag }),
17591912 );
17601913 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{diag});
17611914 }
......@@ -1763,14 +1916,14 @@ test "std.zon structs" {
17631916 // Default field
17641917 {
17651918 const Vec2 = struct { x: f32, y: f32 = 1.5 };
1766 const parsed = try fromSlice(Vec2, gpa, ".{.x = 1.2}", null, .{});
1919 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x = 1.2}", .diag = null });
17671920 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
17681921 }
17691922
17701923 // Comptime field
17711924 {
17721925 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1773 const parsed = try fromSlice(Vec2, gpa, ".{.x = 1.2}", null, .{});
1926 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x = 1.2}", .diag = null });
17741927 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
17751928 }
17761929
......@@ -1779,7 +1932,11 @@ test "std.zon structs" {
17791932 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
17801933 var diag: Diagnostics = .{};
17811934 defer diag.deinit(gpa);
1782 const parsed = fromSlice(Vec2, gpa, ".{.x = 1.2, .y = 1.5}", &diag, .{});
1935 const parsed = fromSlice(Vec2, .{
1936 .gpa = gpa,
1937 .source = ".{.x = 1.2, .y = 1.5}",
1938 .diag = &diag,
1939 });
17831940 try std.testing.expectError(error.ParseZon, parsed);
17841941 try std.testing.expectFmt(
17851942 \\1:18: error: cannot initialize comptime field
......@@ -1791,14 +1948,22 @@ test "std.zon structs" {
17911948 // incorrect way that broke for enum values)
17921949 {
17931950 const Vec0 = struct { x: enum { x } };
1794 const parsed = try fromSlice(Vec0, gpa, ".{ .x = .x }", null, .{});
1951 const parsed = try fromSlice(Vec0, .{
1952 .gpa = gpa,
1953 .source = ".{ .x = .x }",
1954 .diag = null,
1955 });
17951956 try std.testing.expectEqual(Vec0{ .x = .x }, parsed);
17961957 }
17971958
17981959 // Enum field and struct field with @
17991960 {
18001961 const Vec0 = struct { @"x x": enum { @"x x" } };
1801 const parsed = try fromSlice(Vec0, gpa, ".{ .@\"x x\" = .@\"x x\" }", null, .{});
1962 const parsed = try fromSlice(Vec0, .{
1963 .gpa = gpa,
1964 .source = ".{ .@\"x x\" = .@\"x x\" }",
1965 .diag = null,
1966 });
18021967 try std.testing.expectEqual(Vec0{ .@"x x" = .@"x x" }, parsed);
18031968 }
18041969
......@@ -1808,7 +1973,11 @@ test "std.zon structs" {
18081973 {
18091974 var diag: Diagnostics = .{};
18101975 defer diag.deinit(gpa);
1811 const parsed = fromSlice(struct {}, gpa, "Empty{}", &diag, .{});
1976 const parsed = fromSlice(struct {}, .{
1977 .gpa = gpa,
1978 .source = "Empty{}",
1979 .diag = &diag,
1980 });
18121981 try std.testing.expectError(error.ParseZon, parsed);
18131982 try std.testing.expectFmt(
18141983 \\1:1: error: types are not available in ZON
......@@ -1821,7 +1990,11 @@ test "std.zon structs" {
18211990 {
18221991 var diag: Diagnostics = .{};
18231992 defer diag.deinit(gpa);
1824 const parsed = fromSlice([3]u8, gpa, "[3]u8{1, 2, 3}", &diag, .{});
1993 const parsed = fromSlice([3]u8, .{
1994 .gpa = gpa,
1995 .source = "[3]u8{1, 2, 3}",
1996 .diag = &diag,
1997 });
18251998 try std.testing.expectError(error.ParseZon, parsed);
18261999 try std.testing.expectFmt(
18272000 \\1:1: error: types are not available in ZON
......@@ -1834,7 +2007,11 @@ test "std.zon structs" {
18342007 {
18352008 var diag: Diagnostics = .{};
18362009 defer diag.deinit(gpa);
1837 const parsed = fromSliceAlloc([]u8, gpa, "[]u8{1, 2, 3}", &diag, .{});
2010 const parsed = fromSliceAlloc([]u8, .{
2011 .gpa = gpa,
2012 .source = "[]u8{1, 2, 3}",
2013 .diag = &diag,
2014 });
18382015 try std.testing.expectError(error.ParseZon, parsed);
18392016 try std.testing.expectFmt(
18402017 \\1:1: error: types are not available in ZON
......@@ -1847,13 +2024,11 @@ test "std.zon structs" {
18472024 {
18482025 var diag: Diagnostics = .{};
18492026 defer diag.deinit(gpa);
1850 const parsed = fromSlice(
1851 struct { u8, u8, u8 },
1852 gpa,
1853 "Tuple{1, 2, 3}",
1854 &diag,
1855 .{},
1856 );
2027 const parsed = fromSlice(struct { u8, u8, u8 }, .{
2028 .gpa = gpa,
2029 .source = "Tuple{1, 2, 3}",
2030 .diag = &diag,
2031 });
18572032 try std.testing.expectError(error.ParseZon, parsed);
18582033 try std.testing.expectFmt(
18592034 \\1:1: error: types are not available in ZON
......@@ -1866,7 +2041,11 @@ test "std.zon structs" {
18662041 {
18672042 var diag: Diagnostics = .{};
18682043 defer diag.deinit(gpa);
1869 const parsed = fromSlice(struct {}, gpa, ".{ .x = Tuple{1, 2, 3} }", &diag, .{});
2044 const parsed = fromSlice(struct {}, .{
2045 .gpa = gpa,
2046 .source = ".{ .x = Tuple{1, 2, 3} }",
2047 .diag = &diag,
2048 });
18702049 try std.testing.expectError(error.ParseZon, parsed);
18712050 try std.testing.expectFmt(
18722051 \\1:9: error: types are not available in ZON
......@@ -1887,23 +2066,43 @@ test "std.zon tuples" {
18872066 const Tuple2 = struct { f32, bool };
18882067 const Tuple3 = struct { f32, bool, u8 };
18892068
1890 const zero = try fromSlice(Tuple0, gpa, ".{}", null, .{});
2069 const zero = try fromSlice(Tuple0, .{
2070 .gpa = gpa,
2071 .source = ".{}",
2072 .diag = null,
2073 });
18912074 try std.testing.expectEqual(Tuple0{}, zero);
18922075
1893 const one = try fromSlice(Tuple1, gpa, ".{1.2}", null, .{});
2076 const one = try fromSlice(Tuple1, .{
2077 .gpa = gpa,
2078 .source = ".{1.2}",
2079 .diag = null,
2080 });
18942081 try std.testing.expectEqual(Tuple1{1.2}, one);
18952082
1896 const two = try fromSlice(Tuple2, gpa, ".{1.2, true}", null, .{});
2083 const two = try fromSlice(Tuple2, .{
2084 .gpa = gpa,
2085 .source = ".{1.2, true}",
2086 .diag = null,
2087 });
18972088 try std.testing.expectEqual(Tuple2{ 1.2, true }, two);
18982089
1899 const three = try fromSlice(Tuple3, gpa, ".{1.2, false, 3}", null, .{});
2090 const three = try fromSlice(Tuple3, .{
2091 .gpa = gpa,
2092 .source = ".{1.2, false, 3}",
2093 .diag = null,
2094 });
19002095 try std.testing.expectEqual(Tuple3{ 1.2, false, 3 }, three);
19012096 }
19022097
19032098 // Deep free
19042099 {
19052100 const Tuple = struct { []const u8, []const u8 };
1906 const parsed = try fromSliceAlloc(Tuple, gpa, ".{\"hello\", \"world\"}", null, .{});
2101 const parsed = try fromSliceAlloc(Tuple, .{
2102 .gpa = gpa,
2103 .source = ".{\"hello\", \"world\"}",
2104 .diag = null,
2105 });
19072106 defer free(gpa, parsed);
19082107 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);
19092108 }
......@@ -1915,7 +2114,7 @@ test "std.zon tuples" {
19152114 defer diag.deinit(gpa);
19162115 try std.testing.expectError(
19172116 error.ParseZon,
1918 fromSlice(Tuple, gpa, ".{0.5, true, 123}", &diag, .{}),
2117 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{0.5, true, 123}", .diag = &diag }),
19192118 );
19202119 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{diag});
19212120 }
......@@ -1927,7 +2126,7 @@ test "std.zon tuples" {
19272126 defer diag.deinit(gpa);
19282127 try std.testing.expectError(
19292128 error.ParseZon,
1930 fromSlice(Tuple, gpa, ".{0.5}", &diag, .{}),
2129 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{0.5}", .diag = &diag }),
19312130 );
19322131 try std.testing.expectFmt(
19332132 "1:2: error: missing tuple field with index 1\n",
......@@ -1943,7 +2142,7 @@ test "std.zon tuples" {
19432142 defer diag.deinit(gpa);
19442143 try std.testing.expectError(
19452144 error.ParseZon,
1946 fromSlice(Tuple, gpa, ".{.foo = 10.0}", &diag, .{}),
2145 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{.foo = 10.0}", .diag = &diag }),
19472146 );
19482147 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{diag});
19492148 }
......@@ -1955,7 +2154,7 @@ test "std.zon tuples" {
19552154 defer diag.deinit(gpa);
19562155 try std.testing.expectError(
19572156 error.ParseZon,
1958 fromSlice(Struct, gpa, ".{10.0}", &diag, .{}),
2157 fromSlice(Struct, .{ .gpa = gpa, .source = ".{10.0}", .diag = &diag }),
19592158 );
19602159 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{diag});
19612160 }
......@@ -1963,7 +2162,7 @@ test "std.zon tuples" {
19632162 // Comptime field
19642163 {
19652164 const Vec2 = struct { f32, comptime f32 = 1.5 };
1966 const parsed = try fromSlice(Vec2, gpa, ".{ 1.2 }", null, .{});
2165 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{ 1.2 }", .diag = null });
19672166 try std.testing.expectEqual(Vec2{ 1.2, 1.5 }, parsed);
19682167 }
19692168
......@@ -1972,7 +2171,7 @@ test "std.zon tuples" {
19722171 const Vec2 = struct { f32, comptime f32 = 1.5 };
19732172 var diag: Diagnostics = .{};
19742173 defer diag.deinit(gpa);
1975 const parsed = fromSlice(Vec2, gpa, ".{ 1.2, 1.5}", &diag, .{});
2174 const parsed = fromSlice(Vec2, .{ .gpa = gpa, .source = ".{ 1.2, 1.5}", .diag = &diag });
19762175 try std.testing.expectError(error.ParseZon, parsed);
19772176 try std.testing.expectFmt(
19782177 \\1:9: error: cannot initialize comptime field
......@@ -1989,49 +2188,97 @@ test "std.zon arrays and slices" {
19892188 {
19902189 // Arrays
19912190 {
1992 const zero = try fromSlice([0]u8, gpa, ".{}", null, .{});
2191 const zero = try fromSlice([0]u8, .{
2192 .gpa = gpa,
2193 .source = ".{}",
2194 .diag = null,
2195 });
19932196 try std.testing.expectEqualSlices(u8, &@as([0]u8, .{}), &zero);
19942197
1995 const one = try fromSlice([1]u8, gpa, ".{'a'}", null, .{});
2198 const one = try fromSlice([1]u8, .{
2199 .gpa = gpa,
2200 .source = ".{'a'}",
2201 .diag = null,
2202 });
19962203 try std.testing.expectEqualSlices(u8, &@as([1]u8, .{'a'}), &one);
19972204
1998 const two = try fromSlice([2]u8, gpa, ".{'a', 'b'}", null, .{});
2205 const two = try fromSlice([2]u8, .{
2206 .gpa = gpa,
2207 .source = ".{'a', 'b'}",
2208 .diag = null,
2209 });
19992210 try std.testing.expectEqualSlices(u8, &@as([2]u8, .{ 'a', 'b' }), &two);
20002211
2001 const two_comma = try fromSlice([2]u8, gpa, ".{'a', 'b',}", null, .{});
2212 const two_comma = try fromSlice([2]u8, .{
2213 .gpa = gpa,
2214 .source = ".{'a', 'b',}",
2215 .diag = null,
2216 });
20022217 try std.testing.expectEqualSlices(u8, &@as([2]u8, .{ 'a', 'b' }), &two_comma);
20032218
2004 const three = try fromSlice([3]u8, gpa, ".{'a', 'b', 'c'}", null, .{});
2219 const three = try fromSlice([3]u8, .{
2220 .gpa = gpa,
2221 .source = ".{'a', 'b', 'c'}",
2222 .diag = null,
2223 });
20052224 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, &three);
20062225
2007 const sentinel = try fromSlice([3:'z']u8, gpa, ".{'a', 'b', 'c'}", null, .{});
2226 const sentinel = try fromSlice([3:'z']u8, .{
2227 .gpa = gpa,
2228 .source = ".{'a', 'b', 'c'}",
2229 .diag = null,
2230 });
20082231 const expected_sentinel: [3:'z']u8 = .{ 'a', 'b', 'c' };
20092232 try std.testing.expectEqualSlices(u8, &expected_sentinel, &sentinel);
20102233 }
20112234
20122235 // Slice literals
20132236 {
2014 const zero = try fromSliceAlloc([]const u8, gpa, ".{}", null, .{});
2237 const zero = try fromSliceAlloc([]const u8, .{
2238 .gpa = gpa,
2239 .source = ".{}",
2240 .diag = null,
2241 });
20152242 defer free(gpa, zero);
20162243 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);
20172244
2018 const one = try fromSliceAlloc([]u8, gpa, ".{'a'}", null, .{});
2245 const one = try fromSliceAlloc([]u8, .{
2246 .gpa = gpa,
2247 .source = ".{'a'}",
2248 .diag = null,
2249 });
20192250 defer free(gpa, one);
20202251 try std.testing.expectEqualSlices(u8, &.{'a'}, one);
20212252
2022 const two = try fromSliceAlloc([]const u8, gpa, ".{'a', 'b'}", null, .{});
2253 const two = try fromSliceAlloc([]const u8, .{
2254 .gpa = gpa,
2255 .source = ".{'a', 'b'}",
2256 .diag = null,
2257 });
20232258 defer free(gpa, two);
20242259 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);
20252260
2026 const two_comma = try fromSliceAlloc([]const u8, gpa, ".{'a', 'b',}", null, .{});
2261 const two_comma = try fromSliceAlloc([]const u8, .{
2262 .gpa = gpa,
2263 .source = ".{'a', 'b',}",
2264 .diag = null,
2265 });
20272266 defer free(gpa, two_comma);
20282267 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);
20292268
2030 const three = try fromSliceAlloc([]u8, gpa, ".{'a', 'b', 'c'}", null, .{});
2269 const three = try fromSliceAlloc([]u8, .{
2270 .gpa = gpa,
2271 .source = ".{'a', 'b', 'c'}",
2272 .diag = null,
2273 });
20312274 defer free(gpa, three);
20322275 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);
20332276
2034 const sentinel = try fromSliceAlloc([:'z']const u8, gpa, ".{'a', 'b', 'c'}", null, .{});
2277 const sentinel = try fromSliceAlloc([:'z']const u8, .{
2278 .gpa = gpa,
2279 .source = ".{'a', 'b', 'c'}",
2280 .diag = null,
2281 });
20352282 defer free(gpa, sentinel);
20362283 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };
20372284 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);
......@@ -2042,7 +2289,11 @@ test "std.zon arrays and slices" {
20422289 {
20432290 // Arrays
20442291 {
2045 const parsed = try fromSliceAlloc([1][]const u8, gpa, ".{\"abc\"}", null, .{});
2292 const parsed = try fromSliceAlloc([1][]const u8, .{
2293 .gpa = gpa,
2294 .source = ".{\"abc\"}",
2295 .diag = null,
2296 });
20462297 defer free(gpa, parsed);
20472298 const expected: [1][]const u8 = .{"abc"};
20482299 try std.testing.expectEqualDeep(expected, parsed);
......@@ -2050,7 +2301,11 @@ test "std.zon arrays and slices" {
20502301
20512302 // Slice literals
20522303 {
2053 const parsed = try fromSliceAlloc([]const []const u8, gpa, ".{\"abc\"}", null, .{});
2304 const parsed = try fromSliceAlloc([]const []const u8, .{
2305 .gpa = gpa,
2306 .source = ".{\"abc\"}",
2307 .diag = null,
2308 });
20542309 defer free(gpa, parsed);
20552310 const expected: []const []const u8 = &.{"abc"};
20562311 try std.testing.expectEqualDeep(expected, parsed);
......@@ -2061,7 +2316,11 @@ test "std.zon arrays and slices" {
20612316 {
20622317 // Arrays
20632318 {
2064 const sentinel = try fromSlice([1:2]u8, gpa, ".{1}", null, .{});
2319 const sentinel = try fromSlice([1:2]u8, .{
2320 .gpa = gpa,
2321 .source = ".{1}",
2322 .diag = null,
2323 });
20652324 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
20662325 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
20672326 try std.testing.expectEqual(@as(u8, 2), sentinel[1]);
......@@ -2069,7 +2328,11 @@ test "std.zon arrays and slices" {
20692328
20702329 // Slice literals
20712330 {
2072 const sentinel = try fromSliceAlloc([:2]align(4) u8, gpa, ".{1}", null, .{});
2331 const sentinel = try fromSliceAlloc([:2]align(4) u8, .{
2332 .gpa = gpa,
2333 .source = ".{1}",
2334 .diag = null,
2335 });
20732336 defer free(gpa, sentinel);
20742337 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
20752338 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
......@@ -2083,7 +2346,7 @@ test "std.zon arrays and slices" {
20832346 defer diag.deinit(gpa);
20842347 try std.testing.expectError(
20852348 error.ParseZon,
2086 fromSlice([0]u8, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
2349 fromSlice([0]u8, .{ .gpa = gpa, .source = ".{'a', 'b', 'c'}", .diag = &diag }),
20872350 );
20882351 try std.testing.expectFmt(
20892352 "1:3: error: index 0 outside of array of length 0\n",
......@@ -2098,7 +2361,7 @@ test "std.zon arrays and slices" {
20982361 defer diag.deinit(gpa);
20992362 try std.testing.expectError(
21002363 error.ParseZon,
2101 fromSlice([1]u8, gpa, ".{'a', 'b'}", &diag, .{}),
2364 fromSlice([1]u8, .{ .gpa = gpa, .source = ".{'a', 'b'}", .diag = &diag }),
21022365 );
21032366 try std.testing.expectFmt(
21042367 "1:8: error: index 1 outside of array of length 1\n",
......@@ -2113,7 +2376,7 @@ test "std.zon arrays and slices" {
21132376 defer diag.deinit(gpa);
21142377 try std.testing.expectError(
21152378 error.ParseZon,
2116 fromSlice([2]u8, gpa, ".{'a'}", &diag, .{}),
2379 fromSlice([2]u8, .{ .gpa = gpa, .source = ".{'a'}", .diag = &diag }),
21172380 );
21182381 try std.testing.expectFmt(
21192382 "1:2: error: expected 2 array elements; found 1\n",
......@@ -2128,7 +2391,7 @@ test "std.zon arrays and slices" {
21282391 defer diag.deinit(gpa);
21292392 try std.testing.expectError(
21302393 error.ParseZon,
2131 fromSlice([3]u8, gpa, ".{}", &diag, .{}),
2394 fromSlice([3]u8, .{ .gpa = gpa, .source = ".{}", .diag = &diag }),
21322395 );
21332396 try std.testing.expectFmt(
21342397 "1:2: error: expected 3 array elements; found 0\n",
......@@ -2145,7 +2408,7 @@ test "std.zon arrays and slices" {
21452408 defer diag.deinit(gpa);
21462409 try std.testing.expectError(
21472410 error.ParseZon,
2148 fromSlice([3]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
2411 fromSlice([3]bool, .{ .gpa = gpa, .source = ".{'a', 'b', 'c'}", .diag = &diag }),
21492412 );
21502413 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
21512414 }
......@@ -2156,7 +2419,11 @@ test "std.zon arrays and slices" {
21562419 defer diag.deinit(gpa);
21572420 try std.testing.expectError(
21582421 error.ParseZon,
2159 fromSliceAlloc([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
2422 fromSliceAlloc([]bool, .{
2423 .gpa = gpa,
2424 .source = ".{'a', 'b', 'c'}",
2425 .diag = &diag,
2426 }),
21602427 );
21612428 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
21622429 }
......@@ -2170,7 +2437,7 @@ test "std.zon arrays and slices" {
21702437 defer diag.deinit(gpa);
21712438 try std.testing.expectError(
21722439 error.ParseZon,
2173 fromSlice([3]u8, gpa, "'a'", &diag, .{}),
2440 fromSlice([3]u8, .{ .gpa = gpa, .source = "'a'", .diag = &diag }),
21742441 );
21752442 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21762443 }
......@@ -2181,7 +2448,7 @@ test "std.zon arrays and slices" {
21812448 defer diag.deinit(gpa);
21822449 try std.testing.expectError(
21832450 error.ParseZon,
2184 fromSliceAlloc([]u8, gpa, "'a'", &diag, .{}),
2451 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "'a'", .diag = &diag }),
21852452 );
21862453 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21872454 }
......@@ -2193,7 +2460,7 @@ test "std.zon arrays and slices" {
21932460 defer diag.deinit(gpa);
21942461 try std.testing.expectError(
21952462 error.ParseZon,
2196 fromSliceAlloc([]u8, gpa, " &.{'a', 'b', 'c'}", &diag, .{}),
2463 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = " &.{'a', 'b', 'c'}", .diag = &diag }),
21972464 );
21982465 try std.testing.expectFmt(
21992466 "1:3: error: pointers are not available in ZON\n",
......@@ -2208,21 +2475,33 @@ test "std.zon string literal" {
22082475
22092476 // Basic string literal
22102477 {
2211 const parsed = try fromSliceAlloc([]const u8, gpa, "\"abc\"", null, .{});
2478 const parsed = try fromSliceAlloc([]const u8, .{
2479 .gpa = gpa,
2480 .source = "\"abc\"",
2481 .diag = null,
2482 });
22122483 defer free(gpa, parsed);
22132484 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);
22142485 }
22152486
22162487 // String literal with escape characters
22172488 {
2218 const parsed = try fromSliceAlloc([]const u8, gpa, "\"ab\\nc\"", null, .{});
2489 const parsed = try fromSliceAlloc([]const u8, .{
2490 .gpa = gpa,
2491 .source = "\"ab\\nc\"",
2492 .diag = null,
2493 });
22192494 defer free(gpa, parsed);
22202495 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);
22212496 }
22222497
22232498 // String literal with embedded null
22242499 {
2225 const parsed = try fromSliceAlloc([]const u8, gpa, "\"ab\\x00c\"", null, .{});
2500 const parsed = try fromSliceAlloc([]const u8, .{
2501 .gpa = gpa,
2502 .source = "\"ab\\x00c\"",
2503 .diag = null,
2504 });
22262505 defer free(gpa, parsed);
22272506 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);
22282507 }
......@@ -2234,7 +2513,7 @@ test "std.zon string literal" {
22342513 defer diag.deinit(gpa);
22352514 try std.testing.expectError(
22362515 error.ParseZon,
2237 fromSliceAlloc([]u8, gpa, "\"abcd\"", &diag, .{}),
2516 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "\"abcd\"", .diag = &diag }),
22382517 );
22392518 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22402519 }
......@@ -2244,7 +2523,7 @@ test "std.zon string literal" {
22442523 defer diag.deinit(gpa);
22452524 try std.testing.expectError(
22462525 error.ParseZon,
2247 fromSliceAlloc([]u8, gpa, "\\\\abcd", &diag, .{}),
2526 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "\\\\abcd", .diag = &diag }),
22482527 );
22492528 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22502529 }
......@@ -2261,7 +2540,7 @@ test "std.zon string literal" {
22612540 defer diag.deinit(gpa);
22622541 try std.testing.expectError(
22632542 error.ParseZon,
2264 fromSlice([4:0]u8, gpa, "\"abcd\"", &diag, .{}),
2543 fromSlice([4:0]u8, .{ .gpa = gpa, .source = "\"abcd\"", .diag = &diag }),
22652544 );
22662545 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22672546 }
......@@ -2271,7 +2550,7 @@ test "std.zon string literal" {
22712550 defer diag.deinit(gpa);
22722551 try std.testing.expectError(
22732552 error.ParseZon,
2274 fromSlice([4:0]u8, gpa, "\\\\abcd", &diag, .{}),
2553 fromSlice([4:0]u8, .{ .gpa = gpa, .source = "\\\\abcd", .diag = &diag }),
22752554 );
22762555 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22772556 }
......@@ -2280,26 +2559,22 @@ test "std.zon string literal" {
22802559 // Zero terminated slices
22812560 {
22822561 {
2283 const parsed: [:0]const u8 = try fromSliceAlloc(
2284 [:0]const u8,
2285 gpa,
2286 "\"abc\"",
2287 null,
2288 .{},
2289 );
2562 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{
2563 .gpa = gpa,
2564 .source = "\"abc\"",
2565 .diag = null,
2566 });
22902567 defer free(gpa, parsed);
22912568 try std.testing.expectEqualStrings("abc", parsed);
22922569 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
22932570 }
22942571
22952572 {
2296 const parsed: [:0]const u8 = try fromSliceAlloc(
2297 [:0]const u8,
2298 gpa,
2299 "\\\\abc",
2300 null,
2301 .{},
2302 );
2573 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{
2574 .gpa = gpa,
2575 .source = "\\\\abc",
2576 .diag = null,
2577 });
23032578 defer free(gpa, parsed);
23042579 try std.testing.expectEqualStrings("abc", parsed);
23052580 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
......@@ -2313,7 +2588,7 @@ test "std.zon string literal" {
23132588 defer diag.deinit(gpa);
23142589 try std.testing.expectError(
23152590 error.ParseZon,
2316 fromSliceAlloc([:1]const u8, gpa, "\"foo\"", &diag, .{}),
2591 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .source = "\"foo\"", .diag = &diag }),
23172592 );
23182593 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
23192594 }
......@@ -2323,7 +2598,7 @@ test "std.zon string literal" {
23232598 defer diag.deinit(gpa);
23242599 try std.testing.expectError(
23252600 error.ParseZon,
2326 fromSliceAlloc([:1]const u8, gpa, "\\\\foo", &diag, .{}),
2601 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .source = "\\\\foo", .diag = &diag }),
23272602 );
23282603 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
23292604 }
......@@ -2335,7 +2610,7 @@ test "std.zon string literal" {
23352610 defer diag.deinit(gpa);
23362611 try std.testing.expectError(
23372612 error.ParseZon,
2338 fromSliceAlloc([]const u8, gpa, "true", &diag, .{}),
2613 fromSliceAlloc([]const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
23392614 );
23402615 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
23412616 }
......@@ -2346,7 +2621,7 @@ test "std.zon string literal" {
23462621 defer diag.deinit(gpa);
23472622 try std.testing.expectError(
23482623 error.ParseZon,
2349 fromSliceAlloc([]const u8, gpa, ".{false}", &diag, .{}),
2624 fromSliceAlloc([]const u8, .{ .gpa = gpa, .source = ".{false}", .diag = &diag }),
23502625 );
23512626 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
23522627 }
......@@ -2357,7 +2632,7 @@ test "std.zon string literal" {
23572632 defer diag.deinit(gpa);
23582633 try std.testing.expectError(
23592634 error.ParseZon,
2360 fromSliceAlloc([]const i8, gpa, "\"\\a\"", &diag, .{}),
2635 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\"\\a\"", .diag = &diag }),
23612636 );
23622637 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
23632638 }
......@@ -2369,7 +2644,7 @@ test "std.zon string literal" {
23692644 defer diag.deinit(gpa);
23702645 try std.testing.expectError(
23712646 error.ParseZon,
2372 fromSliceAlloc([]const i8, gpa, "\"a\"", &diag, .{}),
2647 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\"a\"", .diag = &diag }),
23732648 );
23742649 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
23752650 }
......@@ -2379,7 +2654,7 @@ test "std.zon string literal" {
23792654 defer diag.deinit(gpa);
23802655 try std.testing.expectError(
23812656 error.ParseZon,
2382 fromSliceAlloc([]const i8, gpa, "\\\\a", &diag, .{}),
2657 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\\\\a", .diag = &diag }),
23832658 );
23842659 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
23852660 }
......@@ -2392,7 +2667,11 @@ test "std.zon string literal" {
23922667 defer diag.deinit(gpa);
23932668 try std.testing.expectError(
23942669 error.ParseZon,
2395 fromSliceAlloc([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
2670 fromSliceAlloc([]align(2) const u8, .{
2671 .gpa = gpa,
2672 .source = "\"abc\"",
2673 .diag = &diag,
2674 }),
23962675 );
23972676 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
23982677 }
......@@ -2402,7 +2681,11 @@ test "std.zon string literal" {
24022681 defer diag.deinit(gpa);
24032682 try std.testing.expectError(
24042683 error.ParseZon,
2405 fromSliceAlloc([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
2684 fromSliceAlloc([]align(2) const u8, .{
2685 .gpa = gpa,
2686 .source = "\\\\abc",
2687 .diag = &diag,
2688 }),
24062689 );
24072690 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
24082691 }
......@@ -2417,7 +2700,9 @@ test "std.zon string literal" {
24172700 message2: String,
24182701 message3: String,
24192702 };
2420 const parsed = try fromSliceAlloc(S, gpa,
2703 const parsed = try fromSliceAlloc(S, .{
2704 .gpa = gpa,
2705 .source =
24212706 \\.{
24222707 \\ .message =
24232708 \\ \\hello, world!
......@@ -2434,7 +2719,9 @@ test "std.zon string literal" {
24342719 \\ \\
24352720 \\ \\and this.
24362721 \\}
2437 , null, .{});
2722 ,
2723 .diag = null,
2724 });
24382725 defer free(gpa, parsed);
24392726 try std.testing.expectEqualStrings(
24402727 "hello, world!\nthis is a multiline string!\n\n...",
......@@ -2457,12 +2744,24 @@ test "std.zon enum literals" {
24572744 };
24582745
24592746 // Tags that exist
2460 try std.testing.expectEqual(Enum.foo, try fromSlice(Enum, gpa, ".foo", null, .{}));
2461 try std.testing.expectEqual(Enum.bar, try fromSlice(Enum, gpa, ".bar", null, .{}));
2462 try std.testing.expectEqual(Enum.baz, try fromSlice(Enum, gpa, ".baz", null, .{}));
2747 try std.testing.expectEqual(Enum.foo, try fromSlice(Enum, .{
2748 .gpa = gpa,
2749 .source = ".foo",
2750 .diag = null,
2751 }));
2752 try std.testing.expectEqual(Enum.bar, try fromSlice(Enum, .{
2753 .gpa = gpa,
2754 .source = ".bar",
2755 .diag = null,
2756 }));
2757 try std.testing.expectEqual(Enum.baz, try fromSlice(Enum, .{
2758 .gpa = gpa,
2759 .source = ".baz",
2760 .diag = null,
2761 }));
24632762 try std.testing.expectEqual(
24642763 Enum.@"ab\nc",
2465 try fromSlice(Enum, gpa, ".@\"ab\\nc\"", null, .{}),
2764 try fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"ab\\nc\"", .diag = null }),
24662765 );
24672766
24682767 // Bad tag
......@@ -2471,7 +2770,7 @@ test "std.zon enum literals" {
24712770 defer diag.deinit(gpa);
24722771 try std.testing.expectError(
24732772 error.ParseZon,
2474 fromSlice(Enum, gpa, ".qux", &diag, .{}),
2773 fromSlice(Enum, .{ .gpa = gpa, .source = ".qux", .diag = &diag }),
24752774 );
24762775 try std.testing.expectFmt(
24772776 \\1:2: error: unexpected enum literal 'qux'
......@@ -2489,7 +2788,7 @@ test "std.zon enum literals" {
24892788 defer diag.deinit(gpa);
24902789 try std.testing.expectError(
24912790 error.ParseZon,
2492 fromSlice(Enum, gpa, ".@\"foobarbaz\"", &diag, .{}),
2791 fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"foobarbaz\"", .diag = &diag }),
24932792 );
24942793 try std.testing.expectFmt(
24952794 \\1:2: error: unexpected enum literal 'foobarbaz'
......@@ -2507,7 +2806,7 @@ test "std.zon enum literals" {
25072806 defer diag.deinit(gpa);
25082807 try std.testing.expectError(
25092808 error.ParseZon,
2510 fromSlice(Enum, gpa, "true", &diag, .{}),
2809 fromSlice(Enum, .{ .gpa = gpa, .source = "true", .diag = &diag }),
25112810 );
25122811 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{diag});
25132812 }
......@@ -2518,7 +2817,7 @@ test "std.zon enum literals" {
25182817 defer diag.deinit(gpa);
25192818 try std.testing.expectError(
25202819 error.ParseZon,
2521 fromSlice(Enum, gpa, ".@\"\\x00\"", &diag, .{}),
2820 fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"\\x00\"", .diag = &diag }),
25222821 );
25232822 try std.testing.expectFmt(
25242823 "1:2: error: identifier cannot contain null bytes\n",
......@@ -2532,8 +2831,16 @@ test "std.zon parse bool" {
25322831 const gpa = std.testing.allocator;
25332832
25342833 // Correct bools
2535 try std.testing.expectEqual(true, try fromSlice(bool, gpa, "true", null, .{}));
2536 try std.testing.expectEqual(false, try fromSlice(bool, gpa, "false", null, .{}));
2834 try std.testing.expectEqual(true, try fromSlice(bool, .{
2835 .gpa = gpa,
2836 .source = "true",
2837 .diag = null,
2838 }));
2839 try std.testing.expectEqual(false, try fromSlice(bool, .{
2840 .gpa = gpa,
2841 .source = "false",
2842 .diag = null,
2843 }));
25372844
25382845 // Errors
25392846 {
......@@ -2541,7 +2848,7 @@ test "std.zon parse bool" {
25412848 defer diag.deinit(gpa);
25422849 try std.testing.expectError(
25432850 error.ParseZon,
2544 fromSlice(bool, gpa, " foo", &diag, .{}),
2851 fromSlice(bool, .{ .gpa = gpa, .source = " foo", .diag = &diag }),
25452852 );
25462853 try std.testing.expectFmt(
25472854 \\1:2: error: invalid expression
......@@ -2553,7 +2860,11 @@ test "std.zon parse bool" {
25532860 {
25542861 var diag: Diagnostics = .{};
25552862 defer diag.deinit(gpa);
2556 try std.testing.expectError(error.ParseZon, fromSlice(bool, gpa, "123", &diag, .{}));
2863 try std.testing.expectError(error.ParseZon, fromSlice(bool, .{
2864 .gpa = gpa,
2865 .source = "123",
2866 .diag = &diag,
2867 }));
25572868 try std.testing.expectFmt("1:1: error: expected type 'bool'\n", "{f}", .{diag});
25582869 }
25592870}
......@@ -2584,52 +2895,102 @@ test "std.zon parse int" {
25842895 const gpa = std.testing.allocator;
25852896
25862897 // Test various numbers and types
2587 try std.testing.expectEqual(@as(u8, 10), try fromSlice(u8, gpa, "10", null, .{}));
2588 try std.testing.expectEqual(@as(i16, 24), try fromSlice(i16, gpa, "24", null, .{}));
2589 try std.testing.expectEqual(@as(i14, -4), try fromSlice(i14, gpa, "-4", null, .{}));
2590 try std.testing.expectEqual(@as(i32, -123), try fromSlice(i32, gpa, "-123", null, .{}));
2898 try std.testing.expectEqual(@as(u8, 10), try fromSlice(u8, .{
2899 .gpa = gpa,
2900 .source = "10",
2901 .diag = null,
2902 }));
2903 try std.testing.expectEqual(@as(i16, 24), try fromSlice(i16, .{
2904 .gpa = gpa,
2905 .source = "24",
2906 .diag = null,
2907 }));
2908 try std.testing.expectEqual(@as(i14, -4), try fromSlice(i14, .{
2909 .gpa = gpa,
2910 .source = "-4",
2911 .diag = null,
2912 }));
2913 try std.testing.expectEqual(@as(i32, -123), try fromSlice(i32, .{
2914 .gpa = gpa,
2915 .source = "-123",
2916 .diag = null,
2917 }));
25912918
25922919 // Test limits
2593 try std.testing.expectEqual(@as(i8, 127), try fromSlice(i8, gpa, "127", null, .{}));
2594 try std.testing.expectEqual(@as(i8, -128), try fromSlice(i8, gpa, "-128", null, .{}));
2920 try std.testing.expectEqual(@as(i8, 127), try fromSlice(i8, .{
2921 .gpa = gpa,
2922 .source = "127",
2923 .diag = null,
2924 }));
2925 try std.testing.expectEqual(@as(i8, -128), try fromSlice(i8, .{
2926 .gpa = gpa,
2927 .source = "-128",
2928 .diag = null,
2929 }));
25952930
25962931 // Test characters
2597 try std.testing.expectEqual(@as(u8, 'a'), try fromSlice(u8, gpa, "'a'", null, .{}));
2598 try std.testing.expectEqual(@as(u8, 'z'), try fromSlice(u8, gpa, "'z'", null, .{}));
2932 try std.testing.expectEqual(@as(u8, 'a'), try fromSlice(u8, .{
2933 .gpa = gpa,
2934 .source = "'a'",
2935 .diag = null,
2936 }));
2937 try std.testing.expectEqual(@as(u8, 'z'), try fromSlice(u8, .{
2938 .gpa = gpa,
2939 .source = "'z'",
2940 .diag = null,
2941 }));
25992942
26002943 // Test big integers
26012944 try std.testing.expectEqual(
26022945 @as(u65, 36893488147419103231),
2603 try fromSlice(u65, gpa, "36893488147419103231", null, .{}),
2946 try fromSlice(u65, .{
2947 .gpa = gpa,
2948 .source = "36893488147419103231",
2949 .diag = null,
2950 }),
26042951 );
26052952 try std.testing.expectEqual(
26062953 @as(u65, 36893488147419103231),
2607 try fromSlice(u65, gpa, "368934_881_474191032_31", null, .{}),
2954 try fromSlice(u65, .{
2955 .gpa = gpa,
2956 .source = "368934_881_474191032_31",
2957 .diag = null,
2958 }),
26082959 );
26092960 try std.testing.expectEqual(
26102961 @as(u128, 340282366920938463463374607431768211455),
2611 try fromSlice(u128, gpa, "340282366920938463463374607431768211455", null, .{}),
2962 try fromSlice(u128, .{
2963 .gpa = gpa,
2964 .source = "340282366920938463463374607431768211455",
2965 .diag = null,
2966 }),
26122967 );
26132968
26142969 // Test big integer limits
26152970 try std.testing.expectEqual(
26162971 @as(i66, 36893488147419103231),
2617 try fromSlice(i66, gpa, "36893488147419103231", null, .{}),
2972 try fromSlice(i66, .{
2973 .gpa = gpa,
2974 .source = "36893488147419103231",
2975 .diag = null,
2976 }),
26182977 );
26192978 try std.testing.expectEqual(
26202979 @as(i66, -36893488147419103232),
2621 try fromSlice(i66, gpa, "-36893488147419103232", null, .{}),
2980 try fromSlice(i66, .{
2981 .gpa = gpa,
2982 .source = "-36893488147419103232",
2983 .diag = null,
2984 }),
26222985 );
26232986 {
26242987 var diag: Diagnostics = .{};
26252988 defer diag.deinit(gpa);
2626 try std.testing.expectError(error.ParseZon, fromSlice(
2627 i66,
2628 gpa,
2629 "36893488147419103232",
2630 &diag,
2631 .{},
2632 ));
2989 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
2990 .gpa = gpa,
2991 .source = "36893488147419103232",
2992 .diag = &diag,
2993 }));
26332994 try std.testing.expectFmt(
26342995 "1:1: error: type 'i66' cannot represent value\n",
26352996 "{f}",
......@@ -2639,13 +3000,11 @@ test "std.zon parse int" {
26393000 {
26403001 var diag: Diagnostics = .{};
26413002 defer diag.deinit(gpa);
2642 try std.testing.expectError(error.ParseZon, fromSlice(
2643 i66,
2644 gpa,
2645 "-36893488147419103233",
2646 &diag,
2647 .{},
2648 ));
3003 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
3004 .gpa = gpa,
3005 .source = "-36893488147419103233",
3006 .diag = &diag,
3007 }));
26493008 try std.testing.expectFmt(
26503009 "1:1: error: type 'i66' cannot represent value\n",
26513010 "{f}",
......@@ -2654,87 +3013,105 @@ test "std.zon parse int" {
26543013 }
26553014
26563015 // Test parsing whole number floats as integers
2657 try std.testing.expectEqual(@as(i8, -1), try fromSlice(i8, gpa, "-1.0", null, .{}));
2658 try std.testing.expectEqual(@as(i8, 123), try fromSlice(i8, gpa, "123.0", null, .{}));
3016 try std.testing.expectEqual(@as(i8, -1), try fromSlice(i8, .{
3017 .gpa = gpa,
3018 .source = "-1.0",
3019 .diag = null,
3020 }));
3021 try std.testing.expectEqual(@as(i8, 123), try fromSlice(i8, .{
3022 .gpa = gpa,
3023 .source = "123.0",
3024 .diag = null,
3025 }));
26593026
26603027 // Test non-decimal integers
2661 try std.testing.expectEqual(@as(i16, 0xff), try fromSlice(i16, gpa, "0xff", null, .{}));
2662 try std.testing.expectEqual(@as(i16, -0xff), try fromSlice(i16, gpa, "-0xff", null, .{}));
2663 try std.testing.expectEqual(@as(i16, 0o77), try fromSlice(i16, gpa, "0o77", null, .{}));
2664 try std.testing.expectEqual(@as(i16, -0o77), try fromSlice(i16, gpa, "-0o77", null, .{}));
2665 try std.testing.expectEqual(@as(i16, 0b11), try fromSlice(i16, gpa, "0b11", null, .{}));
2666 try std.testing.expectEqual(@as(i16, -0b11), try fromSlice(i16, gpa, "-0b11", null, .{}));
3028 try std.testing.expectEqual(@as(i16, 0xff), try fromSlice(i16, .{
3029 .gpa = gpa,
3030 .source = "0xff",
3031 .diag = null,
3032 }));
3033 try std.testing.expectEqual(@as(i16, -0xff), try fromSlice(i16, .{
3034 .gpa = gpa,
3035 .source = "-0xff",
3036 .diag = null,
3037 }));
3038 try std.testing.expectEqual(@as(i16, 0o77), try fromSlice(i16, .{
3039 .gpa = gpa,
3040 .source = "0o77",
3041 .diag = null,
3042 }));
3043 try std.testing.expectEqual(@as(i16, -0o77), try fromSlice(i16, .{
3044 .gpa = gpa,
3045 .source = "-0o77",
3046 .diag = null,
3047 }));
3048 try std.testing.expectEqual(@as(i16, 0b11), try fromSlice(i16, .{
3049 .gpa = gpa,
3050 .source = "0b11",
3051 .diag = null,
3052 }));
3053 try std.testing.expectEqual(@as(i16, -0b11), try fromSlice(i16, .{
3054 .gpa = gpa,
3055 .source = "-0b11",
3056 .diag = null,
3057 }));
26673058
26683059 // Test non-decimal big integers
2669 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(
2670 u65,
2671 gpa,
2672 "0x1ffffffffffffffff",
2673 null,
2674 .{},
2675 ));
2676 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(
2677 i66,
2678 gpa,
2679 "0x1ffffffffffffffff",
2680 null,
2681 .{},
2682 ));
2683 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(
2684 i66,
2685 gpa,
2686 "-0x1ffffffffffffffff",
2687 null,
2688 .{},
2689 ));
2690 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(
2691 u65,
2692 gpa,
2693 "0o3777777777777777777777",
2694 null,
2695 .{},
2696 ));
2697 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(
2698 i66,
2699 gpa,
2700 "0o3777777777777777777777",
2701 null,
2702 .{},
2703 ));
2704 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(
2705 i66,
2706 gpa,
2707 "-0o3777777777777777777777",
2708 null,
2709 .{},
2710 ));
2711 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(
2712 u65,
2713 gpa,
2714 "0b11111111111111111111111111111111111111111111111111111111111111111",
2715 null,
2716 .{},
2717 ));
2718 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(
2719 i66,
2720 gpa,
2721 "0b11111111111111111111111111111111111111111111111111111111111111111",
2722 null,
2723 .{},
2724 ));
2725 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(
2726 i66,
2727 gpa,
2728 "-0b11111111111111111111111111111111111111111111111111111111111111111",
2729 null,
2730 .{},
2731 ));
3060 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(u65, .{
3061 .gpa = gpa,
3062 .source = "0x1ffffffffffffffff",
3063 .diag = null,
3064 }));
3065 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(i66, .{
3066 .gpa = gpa,
3067 .source = "0x1ffffffffffffffff",
3068 .diag = null,
3069 }));
3070 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(i66, .{
3071 .gpa = gpa,
3072 .source = "-0x1ffffffffffffffff",
3073 .diag = null,
3074 }));
3075 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(u65, .{
3076 .gpa = gpa,
3077 .source = "0o3777777777777777777777",
3078 .diag = null,
3079 }));
3080 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(i66, .{
3081 .gpa = gpa,
3082 .source = "0o3777777777777777777777",
3083 .diag = null,
3084 }));
3085 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(i66, .{
3086 .gpa = gpa,
3087 .source = "-0o3777777777777777777777",
3088 .diag = null,
3089 }));
3090 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(u65, .{
3091 .gpa = gpa,
3092 .source = "0b11111111111111111111111111111111111111111111111111111111111111111",
3093 .diag = null,
3094 }));
3095 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(i66, .{
3096 .gpa = gpa,
3097 .source = "0b11111111111111111111111111111111111111111111111111111111111111111",
3098 .diag = null,
3099 }));
3100 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(i66, .{
3101 .gpa = gpa,
3102 .source = "-0b11111111111111111111111111111111111111111111111111111111111111111",
3103 .diag = null,
3104 }));
27323105
27333106 // Number with invalid character in the middle
27343107 {
27353108 var diag: Diagnostics = .{};
27363109 defer diag.deinit(gpa);
2737 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{}));
3110 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3111 .gpa = gpa,
3112 .source = "32a32",
3113 .diag = &diag,
3114 }));
27383115 try std.testing.expectFmt(
27393116 "1:3: error: invalid digit 'a' for decimal base\n",
27403117 "{f}",
......@@ -2746,7 +3123,11 @@ test "std.zon parse int" {
27463123 {
27473124 var diag: Diagnostics = .{};
27483125 defer diag.deinit(gpa);
2749 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "true", &diag, .{}));
3126 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3127 .gpa = gpa,
3128 .source = "true",
3129 .diag = &diag,
3130 }));
27503131 try std.testing.expectFmt("1:1: error: expected type 'u8'\n", "{f}", .{diag});
27513132 }
27523133
......@@ -2754,7 +3135,11 @@ test "std.zon parse int" {
27543135 {
27553136 var diag: Diagnostics = .{};
27563137 defer diag.deinit(gpa);
2757 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{}));
3138 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3139 .gpa = gpa,
3140 .source = "256",
3141 .diag = &diag,
3142 }));
27583143 try std.testing.expectFmt(
27593144 "1:1: error: type 'u8' cannot represent value\n",
27603145 "{f}",
......@@ -2766,7 +3151,11 @@ test "std.zon parse int" {
27663151 {
27673152 var diag: Diagnostics = .{};
27683153 defer diag.deinit(gpa);
2769 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{}));
3154 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3155 .gpa = gpa,
3156 .source = "-129",
3157 .diag = &diag,
3158 }));
27703159 try std.testing.expectFmt(
27713160 "1:1: error: type 'i8' cannot represent value\n",
27723161 "{f}",
......@@ -2778,7 +3167,11 @@ test "std.zon parse int" {
27783167 {
27793168 var diag: Diagnostics = .{};
27803169 defer diag.deinit(gpa);
2781 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{}));
3170 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3171 .gpa = gpa,
3172 .source = "-1",
3173 .diag = &diag,
3174 }));
27823175 try std.testing.expectFmt(
27833176 "1:1: error: type 'u8' cannot represent value\n",
27843177 "{f}",
......@@ -2790,7 +3183,11 @@ test "std.zon parse int" {
27903183 {
27913184 var diag: Diagnostics = .{};
27923185 defer diag.deinit(gpa);
2793 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{}));
3186 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3187 .gpa = gpa,
3188 .source = "1.5",
3189 .diag = &diag,
3190 }));
27943191 try std.testing.expectFmt(
27953192 "1:1: error: type 'u8' cannot represent value\n",
27963193 "{f}",
......@@ -2802,7 +3199,11 @@ test "std.zon parse int" {
28023199 {
28033200 var diag: Diagnostics = .{};
28043201 defer diag.deinit(gpa);
2805 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{}));
3202 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3203 .gpa = gpa,
3204 .source = "-1.0",
3205 .diag = &diag,
3206 }));
28063207 try std.testing.expectFmt(
28073208 "1:1: error: type 'u8' cannot represent value\n",
28083209 "{f}",
......@@ -2814,7 +3215,11 @@ test "std.zon parse int" {
28143215 {
28153216 var diag: Diagnostics = .{};
28163217 defer diag.deinit(gpa);
2817 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-0", &diag, .{}));
3218 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3219 .gpa = gpa,
3220 .source = "-0",
3221 .diag = &diag,
3222 }));
28183223 try std.testing.expectFmt(
28193224 \\1:2: error: integer literal '-0' is ambiguous
28203225 \\1:2: note: use '0' for an integer zero
......@@ -2827,7 +3232,11 @@ test "std.zon parse int" {
28273232 {
28283233 var diag: Diagnostics = .{};
28293234 defer diag.deinit(gpa);
2830 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-0", &diag, .{}));
3235 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3236 .gpa = gpa,
3237 .source = "-0",
3238 .diag = &diag,
3239 }));
28313240 try std.testing.expectFmt(
28323241 \\1:2: error: integer literal '-0' is ambiguous
28333242 \\1:2: note: use '0' for an integer zero
......@@ -2838,15 +3247,27 @@ test "std.zon parse int" {
28383247
28393248 // Negative float 0 is allowed
28403249 try std.testing.expect(
2841 std.math.isNegativeZero(try fromSlice(f32, gpa, "-0.0", null, .{})),
3250 std.math.isNegativeZero(try fromSlice(f32, .{
3251 .gpa = gpa,
3252 .source = "-0.0",
3253 .diag = null,
3254 })),
28423255 );
2843 try std.testing.expect(std.math.isPositiveZero(try fromSlice(f32, gpa, "0.0", null, .{})));
3256 try std.testing.expect(std.math.isPositiveZero(try fromSlice(f32, .{
3257 .gpa = gpa,
3258 .source = "0.0",
3259 .diag = null,
3260 })));
28443261
28453262 // Double negation is not allowed
28463263 {
28473264 var diag: Diagnostics = .{};
28483265 defer diag.deinit(gpa);
2849 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{}));
3266 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3267 .gpa = gpa,
3268 .source = "--2",
3269 .diag = &diag,
3270 }));
28503271 try std.testing.expectFmt(
28513272 "1:1: error: expected number or 'inf' after '-'\n",
28523273 "{f}",
......@@ -2859,7 +3280,7 @@ test "std.zon parse int" {
28593280 defer diag.deinit(gpa);
28603281 try std.testing.expectError(
28613282 error.ParseZon,
2862 fromSlice(f32, gpa, "--2.0", &diag, .{}),
3283 fromSlice(f32, .{ .gpa = gpa, .source = "--2.0", .diag = &diag }),
28633284 );
28643285 try std.testing.expectFmt(
28653286 "1:1: error: expected number or 'inf' after '-'\n",
......@@ -2872,7 +3293,11 @@ test "std.zon parse int" {
28723293 {
28733294 var diag: Diagnostics = .{};
28743295 defer diag.deinit(gpa);
2875 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "0xg", &diag, .{}));
3296 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3297 .gpa = gpa,
3298 .source = "0xg",
3299 .diag = &diag,
3300 }));
28763301 try std.testing.expectFmt("1:3: error: invalid digit 'g' for hex base\n", "{f}", .{diag});
28773302 }
28783303
......@@ -2880,7 +3305,11 @@ test "std.zon parse int" {
28803305 {
28813306 var diag: Diagnostics = .{};
28823307 defer diag.deinit(gpa);
2883 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "0123", &diag, .{}));
3308 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3309 .gpa = gpa,
3310 .source = "0123",
3311 .diag = &diag,
3312 }));
28843313 try std.testing.expectFmt(
28853314 \\1:1: error: number '0123' has leading zero
28863315 \\1:1: note: use '0o' prefix for octal literals
......@@ -2895,7 +3324,11 @@ test "std.zon negative char" {
28953324 {
28963325 var diag: Diagnostics = .{};
28973326 defer diag.deinit(gpa);
2898 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{}));
3327 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3328 .gpa = gpa,
3329 .source = "-'a'",
3330 .diag = &diag,
3331 }));
28993332 try std.testing.expectFmt(
29003333 "1:1: error: expected number or 'inf' after '-'\n",
29013334 "{f}",
......@@ -2905,7 +3338,11 @@ test "std.zon negative char" {
29053338 {
29063339 var diag: Diagnostics = .{};
29073340 defer diag.deinit(gpa);
2908 try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{}));
3341 try std.testing.expectError(error.ParseZon, fromSlice(i16, .{
3342 .gpa = gpa,
3343 .source = "-'a'",
3344 .diag = &diag,
3345 }));
29093346 try std.testing.expectFmt(
29103347 "1:1: error: expected number or 'inf' after '-'\n",
29113348 "{f}",
......@@ -2918,81 +3355,149 @@ test "std.zon parse float" {
29183355 const gpa = std.testing.allocator;
29193356
29203357 // Test decimals
2921 try std.testing.expectEqual(@as(f16, 0.5), try fromSlice(f16, gpa, "0.5", null, .{}));
3358 try std.testing.expectEqual(@as(f16, 0.5), try fromSlice(f16, .{
3359 .gpa = gpa,
3360 .source = "0.5",
3361 .diag = null,
3362 }));
29223363 try std.testing.expectEqual(
29233364 @as(f32, 123.456),
2924 try fromSlice(f32, gpa, "123.456", null, .{}),
3365 try fromSlice(f32, .{ .gpa = gpa, .source = "123.456", .diag = null }),
29253366 );
29263367 try std.testing.expectEqual(
29273368 @as(f64, -123.456),
2928 try fromSlice(f64, gpa, "-123.456", null, .{}),
3369 try fromSlice(f64, .{ .gpa = gpa, .source = "-123.456", .diag = null }),
29293370 );
2930 try std.testing.expectEqual(@as(f128, 42.5), try fromSlice(f128, gpa, "42.5", null, .{}));
3371 try std.testing.expectEqual(@as(f128, 42.5), try fromSlice(f128, .{
3372 .gpa = gpa,
3373 .source = "42.5",
3374 .diag = null,
3375 }));
29313376
29323377 // Test whole numbers with and without decimals
2933 try std.testing.expectEqual(@as(f16, 5.0), try fromSlice(f16, gpa, "5.0", null, .{}));
2934 try std.testing.expectEqual(@as(f16, 5.0), try fromSlice(f16, gpa, "5", null, .{}));
2935 try std.testing.expectEqual(@as(f32, -102), try fromSlice(f32, gpa, "-102.0", null, .{}));
2936 try std.testing.expectEqual(@as(f32, -102), try fromSlice(f32, gpa, "-102", null, .{}));
3378 try std.testing.expectEqual(@as(f16, 5.0), try fromSlice(f16, .{
3379 .gpa = gpa,
3380 .source = "5.0",
3381 .diag = null,
3382 }));
3383 try std.testing.expectEqual(@as(f16, 5.0), try fromSlice(f16, .{
3384 .gpa = gpa,
3385 .source = "5",
3386 .diag = null,
3387 }));
3388 try std.testing.expectEqual(@as(f32, -102), try fromSlice(f32, .{
3389 .gpa = gpa,
3390 .source = "-102.0",
3391 .diag = null,
3392 }));
3393 try std.testing.expectEqual(@as(f32, -102), try fromSlice(f32, .{
3394 .gpa = gpa,
3395 .source = "-102",
3396 .diag = null,
3397 }));
29373398
29383399 // Test characters and negated characters
2939 try std.testing.expectEqual(@as(f32, 'a'), try fromSlice(f32, gpa, "'a'", null, .{}));
2940 try std.testing.expectEqual(@as(f32, 'z'), try fromSlice(f32, gpa, "'z'", null, .{}));
3400 try std.testing.expectEqual(@as(f32, 'a'), try fromSlice(f32, .{
3401 .gpa = gpa,
3402 .source = "'a'",
3403 .diag = null,
3404 }));
3405 try std.testing.expectEqual(@as(f32, 'z'), try fromSlice(f32, .{
3406 .gpa = gpa,
3407 .source = "'z'",
3408 .diag = null,
3409 }));
29413410
29423411 // Test big integers
29433412 try std.testing.expectEqual(
29443413 @as(f32, 36893488147419103231.0),
2945 try fromSlice(f32, gpa, "36893488147419103231", null, .{}),
3414 try fromSlice(f32, .{
3415 .gpa = gpa,
3416 .source = "36893488147419103231",
3417 .diag = null,
3418 }),
29463419 );
29473420 try std.testing.expectEqual(
29483421 @as(f32, -36893488147419103231.0),
2949 try fromSlice(f32, gpa, "-36893488147419103231", null, .{}),
3422 try fromSlice(f32, .{
3423 .gpa = gpa,
3424 .source = "-36893488147419103231",
3425 .diag = null,
3426 }),
29503427 );
2951 try std.testing.expectEqual(@as(f128, 0x1ffffffffffffffff), try fromSlice(
2952 f128,
2953 gpa,
2954 "0x1ffffffffffffffff",
2955 null,
2956 .{},
2957 ));
2958 try std.testing.expectEqual(@as(f32, @floatFromInt(0x1ffffffffffffffff)), try fromSlice(
2959 f32,
2960 gpa,
2961 "0x1ffffffffffffffff",
2962 null,
2963 .{},
2964 ));
3428 try std.testing.expectEqual(@as(f128, 0x1ffffffffffffffff), try fromSlice(f128, .{
3429 .gpa = gpa,
3430 .source = "0x1ffffffffffffffff",
3431 .diag = null,
3432 }));
3433 try std.testing.expectEqual(@as(f32, @floatFromInt(0x1ffffffffffffffff)), try fromSlice(f32, .{
3434 .gpa = gpa,
3435 .source = "0x1ffffffffffffffff",
3436 .diag = null,
3437 }));
29653438
29663439 // Exponents, underscores
29673440 try std.testing.expectEqual(
29683441 @as(f32, 123.0E+77),
2969 try fromSlice(f32, gpa, "12_3.0E+77", null, .{}),
3442 try fromSlice(f32, .{
3443 .gpa = gpa,
3444 .source = "12_3.0E+77",
3445 .diag = null,
3446 }),
29703447 );
29713448
29723449 // Hexadecimal
29733450 try std.testing.expectEqual(
29743451 @as(f32, 0x103.70p-5),
2975 try fromSlice(f32, gpa, "0x103.70p-5", null, .{}),
3452 try fromSlice(f32, .{
3453 .gpa = gpa,
3454 .source = "0x103.70p-5",
3455 .diag = null,
3456 }),
29763457 );
29773458 try std.testing.expectEqual(
29783459 @as(f32, -0x103.70),
2979 try fromSlice(f32, gpa, "-0x103.70", null, .{}),
3460 try fromSlice(f32, .{
3461 .gpa = gpa,
3462 .source = "-0x103.70",
3463 .diag = null,
3464 }),
29803465 );
29813466 try std.testing.expectEqual(
29823467 @as(f32, 0x1234_5678.9ABC_CDEFp-10),
2983 try fromSlice(f32, gpa, "0x1234_5678.9ABC_CDEFp-10", null, .{}),
3468 try fromSlice(f32, .{
3469 .gpa = gpa,
3470 .source = "0x1234_5678.9ABC_CDEFp-10",
3471 .diag = null,
3472 }),
29843473 );
29853474
29863475 // inf, nan
2987 try std.testing.expect(std.math.isPositiveInf(try fromSlice(f32, gpa, "inf", null, .{})));
2988 try std.testing.expect(std.math.isNegativeInf(try fromSlice(f32, gpa, "-inf", null, .{})));
2989 try std.testing.expect(std.math.isNan(try fromSlice(f32, gpa, "nan", null, .{})));
3476 try std.testing.expect(std.math.isPositiveInf(try fromSlice(f32, .{
3477 .gpa = gpa,
3478 .source = "inf",
3479 .diag = null,
3480 })));
3481 try std.testing.expect(std.math.isNegativeInf(try fromSlice(f32, .{
3482 .gpa = gpa,
3483 .source = "-inf",
3484 .diag = null,
3485 })));
3486 try std.testing.expect(std.math.isNan(try fromSlice(f32, .{
3487 .gpa = gpa,
3488 .source = "nan",
3489 .diag = null,
3490 })));
29903491
29913492 // Negative nan not allowed
29923493 {
29933494 var diag: Diagnostics = .{};
29943495 defer diag.deinit(gpa);
2995 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{}));
3496 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3497 .gpa = gpa,
3498 .source = "-nan",
3499 .diag = &diag,
3500 }));
29963501 try std.testing.expectFmt(
29973502 "1:1: error: expected number or 'inf' after '-'\n",
29983503 "{f}",
......@@ -3004,7 +3509,11 @@ test "std.zon parse float" {
30043509 {
30053510 var diag: Diagnostics = .{};
30063511 defer diag.deinit(gpa);
3007 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));
3512 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3513 .gpa = gpa,
3514 .source = "nan",
3515 .diag = &diag,
3516 }));
30083517 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
30093518 }
30103519
......@@ -3012,7 +3521,11 @@ test "std.zon parse float" {
30123521 {
30133522 var diag: Diagnostics = .{};
30143523 defer diag.deinit(gpa);
3015 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));
3524 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3525 .gpa = gpa,
3526 .source = "nan",
3527 .diag = &diag,
3528 }));
30163529 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
30173530 }
30183531
......@@ -3020,7 +3533,11 @@ test "std.zon parse float" {
30203533 {
30213534 var diag: Diagnostics = .{};
30223535 defer diag.deinit(gpa);
3023 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "inf", &diag, .{}));
3536 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3537 .gpa = gpa,
3538 .source = "inf",
3539 .diag = &diag,
3540 }));
30243541 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
30253542 }
30263543
......@@ -3028,7 +3545,11 @@ test "std.zon parse float" {
30283545 {
30293546 var diag: Diagnostics = .{};
30303547 defer diag.deinit(gpa);
3031 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-inf", &diag, .{}));
3548 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3549 .gpa = gpa,
3550 .source = "-inf",
3551 .diag = &diag,
3552 }));
30323553 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
30333554 }
30343555
......@@ -3036,7 +3557,11 @@ test "std.zon parse float" {
30363557 {
30373558 var diag: Diagnostics = .{};
30383559 defer diag.deinit(gpa);
3039 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "foo", &diag, .{}));
3560 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3561 .gpa = gpa,
3562 .source = "foo",
3563 .diag = &diag,
3564 }));
30403565 try std.testing.expectFmt(
30413566 \\1:1: error: invalid expression
30423567 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
......@@ -3048,7 +3573,11 @@ test "std.zon parse float" {
30483573 {
30493574 var diag: Diagnostics = .{};
30503575 defer diag.deinit(gpa);
3051 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{}));
3576 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3577 .gpa = gpa,
3578 .source = "-foo",
3579 .diag = &diag,
3580 }));
30523581 try std.testing.expectFmt(
30533582 "1:1: error: expected number or 'inf' after '-'\n",
30543583 "{f}",
......@@ -3062,7 +3591,7 @@ test "std.zon parse float" {
30623591 defer diag.deinit(gpa);
30633592 try std.testing.expectError(
30643593 error.ParseZon,
3065 fromSlice(f32, gpa, "\"foo\"", &diag, .{}),
3594 fromSlice(f32, .{ .gpa = gpa, .source = "\"foo\"", .diag = &diag }),
30663595 );
30673596 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{diag});
30683597 }
......@@ -3076,13 +3605,17 @@ test "std.zon free on error" {
30763605 y: []const u8,
30773606 z: bool,
30783607 };
3079 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
3608 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3609 .gpa = std.testing.allocator,
3610 .source =
30803611 \\.{
30813612 \\ .x = "hello",
30823613 \\ .y = "world",
30833614 \\ .z = "fail",
30843615 \\}
3085 , null, .{}));
3616 ,
3617 .diag = null,
3618 }));
30863619 }
30873620
30883621 // Test freeing partially allocated tuples
......@@ -3092,13 +3625,17 @@ test "std.zon free on error" {
30923625 []const u8,
30933626 bool,
30943627 };
3095 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
3628 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3629 .gpa = std.testing.allocator,
3630 .source =
30963631 \\.{
30973632 \\ "hello",
30983633 \\ "world",
30993634 \\ "fail",
31003635 \\}
3101 , null, .{}));
3636 ,
3637 .diag = null,
3638 }));
31023639 }
31033640
31043641 // Test freeing structs with missing fields
......@@ -3107,62 +3644,66 @@ test "std.zon free on error" {
31073644 x: []const u8,
31083645 y: bool,
31093646 };
3110 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
3647 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3648 .gpa = std.testing.allocator,
3649 .source =
31113650 \\.{
31123651 \\ .x = "hello",
31133652 \\}
3114 , null, .{}));
3653 ,
3654 .diag = null,
3655 }));
31153656 }
31163657
31173658 // Test freeing partially allocated arrays
31183659 {
3119 try std.testing.expectError(error.ParseZon, fromSliceAlloc(
3120 [3][]const u8,
3121 std.testing.allocator,
3660 try std.testing.expectError(error.ParseZon, fromSliceAlloc([3][]const u8, .{
3661 .gpa = std.testing.allocator,
3662 .source =
31223663 \\.{
31233664 \\ "hello",
31243665 \\ false,
31253666 \\ false,
31263667 \\}
3127 ,
3128 null,
3129 .{},
3130 ));
3668 ,
3669 .diag = null,
3670 }));
31313671 }
31323672
31333673 // Test freeing partially allocated slices
31343674 {
3135 try std.testing.expectError(error.ParseZon, fromSliceAlloc(
3136 [][]const u8,
3137 std.testing.allocator,
3675 try std.testing.expectError(error.ParseZon, fromSliceAlloc([][]const u8, .{
3676 .gpa = std.testing.allocator,
3677 .source =
31383678 \\.{
31393679 \\ "hello",
31403680 \\ "world",
31413681 \\ false,
31423682 \\}
3143 ,
3144 null,
3145 .{},
3146 ));
3683 ,
3684 .diag = null,
3685 }));
31473686 }
31483687
31493688 // We can parse types that can't be freed, as long as they contain no allocations, e.g. untagged
31503689 // unions.
31513690 try std.testing.expectEqual(
31523691 @as(f32, 1.5),
3153 (try fromSlice(union { x: f32 }, std.testing.allocator, ".{ .x = 1.5 }", null, .{})).x,
3692 (try fromSlice(union { x: f32 }, .{
3693 .gpa = std.testing.allocator,
3694 .source = ".{ .x = 1.5 }",
3695 .diag = null,
3696 })).x,
31543697 );
31553698
31563699 // We can also parse types that can't be freed if it's impossible for an error to occur after
31573700 // the allocation, as is the case here.
31583701 {
3159 const result = try fromSliceAlloc(
3160 union { x: []const u8 },
3161 std.testing.allocator,
3162 ".{ .x = \"foo\" }",
3163 null,
3164 .{},
3165 );
3702 const result = try fromSliceAlloc(union { x: []const u8 }, .{
3703 .gpa = std.testing.allocator,
3704 .source = ".{ .x = \"foo\" }",
3705 .diag = null,
3706 });
31663707 defer free(std.testing.allocator, result.x);
31673708 try std.testing.expectEqualStrings("foo", result.x);
31683709 }
......@@ -3175,13 +3716,12 @@ test "std.zon free on error" {
31753716 union { x: []const u8 },
31763717 bool,
31773718 };
3178 const result = try fromSliceAlloc(
3179 S,
3180 std.testing.allocator,
3181 ".{ .{ .x = \"foo\" }, true }",
3182 null,
3183 .{ .free_on_error = false },
3184 );
3719 const result = try fromSliceAlloc(S, .{
3720 .gpa = std.testing.allocator,
3721 .source = ".{ .{ .x = \"foo\" }, true }",
3722 .free_on_error = false,
3723 .diag = null,
3724 });
31853725 defer free(std.testing.allocator, result[0].x);
31863726 try std.testing.expectEqualStrings("foo", result[0].x);
31873727 try std.testing.expect(result[1]);
......@@ -3193,15 +3733,12 @@ test "std.zon free on error" {
31933733 a: union { x: []const u8 },
31943734 b: bool,
31953735 };
3196 const result = try fromSliceAlloc(
3197 S,
3198 std.testing.allocator,
3199 ".{ .a = .{ .x = \"foo\" }, .b = true }",
3200 null,
3201 .{
3202 .free_on_error = false,
3203 },
3204 );
3736 const result = try fromSliceAlloc(S, .{
3737 .gpa = std.testing.allocator,
3738 .source = ".{ .a = .{ .x = \"foo\" }, .b = true }",
3739 .free_on_error = false,
3740 .diag = null,
3741 });
32053742 defer free(std.testing.allocator, result.a.x);
32063743 try std.testing.expectEqualStrings("foo", result.a.x);
32073744 try std.testing.expect(result.b);
......@@ -3210,15 +3747,12 @@ test "std.zon free on error" {
32103747 // Again but for arrays.
32113748 {
32123749 const S = [2]union { x: []const u8 };
3213 const result = try fromSliceAlloc(
3214 S,
3215 std.testing.allocator,
3216 ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
3217 null,
3218 .{
3219 .free_on_error = false,
3220 },
3221 );
3750 const result = try fromSliceAlloc(S, .{
3751 .gpa = std.testing.allocator,
3752 .source = ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
3753 .free_on_error = false,
3754 .diag = null,
3755 });
32223756 defer free(std.testing.allocator, result[0].x);
32233757 defer free(std.testing.allocator, result[1].x);
32243758 try std.testing.expectEqualStrings("foo", result[0].x);
......@@ -3228,15 +3762,12 @@ test "std.zon free on error" {
32283762 // Again but for slices.
32293763 {
32303764 const S = []union { x: []const u8 };
3231 const result = try fromSliceAlloc(
3232 S,
3233 std.testing.allocator,
3234 ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
3235 null,
3236 .{
3237 .free_on_error = false,
3238 },
3239 );
3765 const result = try fromSliceAlloc(S, .{
3766 .gpa = std.testing.allocator,
3767 .source = ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
3768 .free_on_error = false,
3769 .diag = null,
3770 });
32403771 defer std.testing.allocator.free(result);
32413772 defer free(std.testing.allocator, result[0].x);
32423773 defer free(std.testing.allocator, result[1].x);
......@@ -3254,37 +3785,53 @@ test "std.zon vector" {
32543785 // Passing cases
32553786 try std.testing.expectEqual(
32563787 @Vector(0, bool){},
3257 try fromSlice(@Vector(0, bool), gpa, ".{}", null, .{}),
3788 try fromSlice(@Vector(0, bool), .{ .gpa = gpa, .source = ".{}", .diag = null }),
32583789 );
32593790 try std.testing.expectEqual(
32603791 @Vector(3, bool){ true, false, true },
3261 try fromSlice(@Vector(3, bool), gpa, ".{true, false, true}", null, .{}),
3792 try fromSlice(@Vector(3, bool), .{
3793 .gpa = gpa,
3794 .source = ".{true, false, true}",
3795 .diag = null,
3796 }),
32623797 );
32633798
32643799 try std.testing.expectEqual(
32653800 @Vector(0, f32){},
3266 try fromSlice(@Vector(0, f32), gpa, ".{}", null, .{}),
3801 try fromSlice(@Vector(0, f32), .{ .gpa = gpa, .source = ".{}", .diag = null }),
32673802 );
32683803 try std.testing.expectEqual(
32693804 @Vector(3, f32){ 1.5, 2.5, 3.5 },
3270 try fromSlice(@Vector(3, f32), gpa, ".{1.5, 2.5, 3.5}", null, .{}),
3805 try fromSlice(@Vector(3, f32), .{
3806 .gpa = gpa,
3807 .source = ".{1.5, 2.5, 3.5}",
3808 .diag = null,
3809 }),
32713810 );
32723811
32733812 try std.testing.expectEqual(
32743813 @Vector(0, u8){},
3275 try fromSlice(@Vector(0, u8), gpa, ".{}", null, .{}),
3814 try fromSlice(@Vector(0, u8), .{ .gpa = gpa, .source = ".{}", .diag = null }),
32763815 );
32773816 try std.testing.expectEqual(
32783817 @Vector(3, u8){ 2, 4, 6 },
3279 try fromSlice(@Vector(3, u8), gpa, ".{2, 4, 6}", null, .{}),
3818 try fromSlice(@Vector(3, u8), .{ .gpa = gpa, .source = ".{2, 4, 6}", .diag = null }),
32803819 );
32813820
32823821 {
32833822 try std.testing.expectEqual(
32843823 @Vector(0, *const u8){},
3285 try fromSliceAlloc(@Vector(0, *const u8), gpa, ".{}", null, .{}),
3824 try fromSliceAlloc(@Vector(0, *const u8), .{
3825 .gpa = gpa,
3826 .source = ".{}",
3827 .diag = null,
3828 }),
32863829 );
3287 const pointers = try fromSliceAlloc(@Vector(3, *const u8), gpa, ".{2, 4, 6}", null, .{});
3830 const pointers = try fromSliceAlloc(@Vector(3, *const u8), .{
3831 .gpa = gpa,
3832 .source = ".{2, 4, 6}",
3833 .diag = null,
3834 });
32883835 defer free(gpa, pointers);
32893836 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);
32903837 }
......@@ -3292,9 +3839,17 @@ test "std.zon vector" {
32923839 {
32933840 try std.testing.expectEqual(
32943841 @Vector(0, ?*const u8){},
3295 try fromSliceAlloc(@Vector(0, ?*const u8), gpa, ".{}", null, .{}),
3842 try fromSliceAlloc(@Vector(0, ?*const u8), .{
3843 .gpa = gpa,
3844 .source = ".{}",
3845 .diag = null,
3846 }),
32963847 );
3297 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), gpa, ".{2, null, 6}", null, .{});
3848 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), .{
3849 .gpa = gpa,
3850 .source = ".{2, null, 6}",
3851 .diag = null,
3852 });
32983853 defer free(gpa, pointers);
32993854 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);
33003855 }
......@@ -3305,7 +3860,11 @@ test "std.zon vector" {
33053860 defer diag.deinit(gpa);
33063861 try std.testing.expectError(
33073862 error.ParseZon,
3308 fromSlice(@Vector(2, f32), gpa, ".{0.5}", &diag, .{}),
3863 fromSlice(@Vector(2, f32), .{
3864 .gpa = gpa,
3865 .source = ".{0.5}",
3866 .diag = &diag,
3867 }),
33093868 );
33103869 try std.testing.expectFmt(
33113870 "1:2: error: expected 2 array elements; found 1\n",
......@@ -3320,7 +3879,11 @@ test "std.zon vector" {
33203879 defer diag.deinit(gpa);
33213880 try std.testing.expectError(
33223881 error.ParseZon,
3323 fromSlice(@Vector(2, f32), gpa, ".{0.5, 1.5, 2.5}", &diag, .{}),
3882 fromSlice(@Vector(2, f32), .{
3883 .gpa = gpa,
3884 .source = ".{0.5, 1.5, 2.5}",
3885 .diag = &diag,
3886 }),
33243887 );
33253888 try std.testing.expectFmt(
33263889 "1:13: error: index 2 outside of array of length 2\n",
......@@ -3335,7 +3898,11 @@ test "std.zon vector" {
33353898 defer diag.deinit(gpa);
33363899 try std.testing.expectError(
33373900 error.ParseZon,
3338 fromSlice(@Vector(3, f32), gpa, ".{0.5, true, 2.5}", &diag, .{}),
3901 fromSlice(@Vector(3, f32), .{
3902 .gpa = gpa,
3903 .source = ".{0.5, true, 2.5}",
3904 .diag = &diag,
3905 }),
33393906 );
33403907 try std.testing.expectFmt(
33413908 "1:8: error: expected type 'f32'\n",
......@@ -3350,7 +3917,7 @@ test "std.zon vector" {
33503917 defer diag.deinit(gpa);
33513918 try std.testing.expectError(
33523919 error.ParseZon,
3353 fromSlice(@Vector(3, u8), gpa, "true", &diag, .{}),
3920 fromSlice(@Vector(3, u8), .{ .gpa = gpa, .source = "true", .diag = &diag }),
33543921 );
33553922 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{diag});
33563923 }
......@@ -3361,7 +3928,11 @@ test "std.zon vector" {
33613928 defer diag.deinit(gpa);
33623929 try std.testing.expectError(
33633930 error.ParseZon,
3364 fromSliceAlloc(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
3931 fromSliceAlloc(@Vector(3, *u8), .{
3932 .gpa = gpa,
3933 .source = ".{1, true, 3}",
3934 .diag = &diag,
3935 }),
33653936 );
33663937 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{f}", .{diag});
33673938 }
......@@ -3372,77 +3943,133 @@ test "std.zon add pointers" {
33723943
33733944 // Primitive with varying levels of pointers
33743945 {
3375 const result = try fromSliceAlloc(*u32, gpa, "10", null, .{});
3946 const result = try fromSliceAlloc(*u32, .{
3947 .gpa = gpa,
3948 .source = "10",
3949 .diag = null,
3950 });
33763951 defer free(gpa, result);
33773952 try std.testing.expectEqual(@as(u32, 10), result.*);
33783953 }
33793954
33803955 {
3381 const result = try fromSliceAlloc(**u32, gpa, "10", null, .{});
3956 const result = try fromSliceAlloc(**u32, .{
3957 .gpa = gpa,
3958 .source = "10",
3959 .diag = null,
3960 });
33823961 defer free(gpa, result);
33833962 try std.testing.expectEqual(@as(u32, 10), result.*.*);
33843963 }
33853964
33863965 {
3387 const result = try fromSliceAlloc(***u32, gpa, "10", null, .{});
3966 const result = try fromSliceAlloc(***u32, .{
3967 .gpa = gpa,
3968 .source = "10",
3969 .diag = null,
3970 });
33883971 defer free(gpa, result);
33893972 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);
33903973 }
33913974
33923975 // Primitive optional with varying levels of pointers
33933976 {
3394 const some = try fromSliceAlloc(?*u32, gpa, "10", null, .{});
3977 const some = try fromSliceAlloc(?*u32, .{
3978 .gpa = gpa,
3979 .source = "10",
3980 .diag = null,
3981 });
33953982 defer free(gpa, some);
33963983 try std.testing.expectEqual(@as(u32, 10), some.?.*);
33973984
3398 const none = try fromSliceAlloc(?*u32, gpa, "null", null, .{});
3985 const none = try fromSliceAlloc(?*u32, .{
3986 .gpa = gpa,
3987 .source = "null",
3988 .diag = null,
3989 });
33993990 defer free(gpa, none);
34003991 try std.testing.expectEqual(null, none);
34013992 }
34023993
34033994 {
3404 const some = try fromSliceAlloc(*?u32, gpa, "10", null, .{});
3995 const some = try fromSliceAlloc(*?u32, .{
3996 .gpa = gpa,
3997 .source = "10",
3998 .diag = null,
3999 });
34054000 defer free(gpa, some);
34064001 try std.testing.expectEqual(@as(u32, 10), some.*.?);
34074002
3408 const none = try fromSliceAlloc(*?u32, gpa, "null", null, .{});
4003 const none = try fromSliceAlloc(*?u32, .{
4004 .gpa = gpa,
4005 .source = "null",
4006 .diag = null,
4007 });
34094008 defer free(gpa, none);
34104009 try std.testing.expectEqual(null, none.*);
34114010 }
34124011
34134012 {
3414 const some = try fromSliceAlloc(?**u32, gpa, "10", null, .{});
4013 const some = try fromSliceAlloc(?**u32, .{
4014 .gpa = gpa,
4015 .source = "10",
4016 .diag = null,
4017 });
34154018 defer free(gpa, some);
34164019 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);
34174020
3418 const none = try fromSliceAlloc(?**u32, gpa, "null", null, .{});
4021 const none = try fromSliceAlloc(?**u32, .{
4022 .gpa = gpa,
4023 .source = "null",
4024 .diag = null,
4025 });
34194026 defer free(gpa, none);
34204027 try std.testing.expectEqual(null, none);
34214028 }
34224029
34234030 {
3424 const some = try fromSliceAlloc(*?*u32, gpa, "10", null, .{});
4031 const some = try fromSliceAlloc(*?*u32, .{
4032 .gpa = gpa,
4033 .source = "10",
4034 .diag = null,
4035 });
34254036 defer free(gpa, some);
34264037 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);
34274038
3428 const none = try fromSliceAlloc(*?*u32, gpa, "null", null, .{});
4039 const none = try fromSliceAlloc(*?*u32, .{
4040 .gpa = gpa,
4041 .source = "null",
4042 .diag = null,
4043 });
34294044 defer free(gpa, none);
34304045 try std.testing.expectEqual(null, none.*);
34314046 }
34324047
34334048 {
3434 const some = try fromSliceAlloc(**?u32, gpa, "10", null, .{});
4049 const some = try fromSliceAlloc(**?u32, .{
4050 .gpa = gpa,
4051 .source = "10",
4052 .diag = null,
4053 });
34354054 defer free(gpa, some);
34364055 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);
34374056
3438 const none = try fromSliceAlloc(**?u32, gpa, "null", null, .{});
4057 const none = try fromSliceAlloc(**?u32, .{
4058 .gpa = gpa,
4059 .source = "null",
4060 .diag = null,
4061 });
34394062 defer free(gpa, none);
34404063 try std.testing.expectEqual(null, none.*.*);
34414064 }
34424065
34434066 // Pointer to an array
34444067 {
3445 const result = try fromSliceAlloc(*[3]u8, gpa, ".{ 1, 2, 3 }", null, .{});
4068 const result = try fromSliceAlloc(*[3]u8, .{
4069 .gpa = gpa,
4070 .source = ".{ 1, 2, 3 }",
4071 .diag = null,
4072 });
34464073 defer free(gpa, result);
34474074 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);
34484075 }
......@@ -3465,7 +4092,9 @@ test "std.zon add pointers" {
34654092 .f2 = &null,
34664093 };
34674094
3468 const found = try fromSliceAlloc(?*Outer, gpa,
4095 const found = try fromSliceAlloc(?*Outer, .{
4096 .gpa = gpa,
4097 .source =
34694098 \\.{
34704099 \\ .f1 = .{
34714100 \\ .f1 = null,
......@@ -3473,7 +4102,9 @@ test "std.zon add pointers" {
34734102 \\ },
34744103 \\ .f2 = null,
34754104 \\}
3476 , null, .{});
4105 ,
4106 .diag = null,
4107 });
34774108 defer free(gpa, found);
34784109
34794110 try std.testing.expectEqualDeep(expected, found.?.*);
......@@ -3485,7 +4116,7 @@ test "std.zon add pointers" {
34854116 defer diag.deinit(gpa);
34864117 try std.testing.expectError(
34874118 error.ParseZon,
3488 fromSliceAlloc(*const ?*const u8, gpa, "true", &diag, .{}),
4119 fromSliceAlloc(*const ?*const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
34894120 );
34904121 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
34914122 }
......@@ -3495,7 +4126,7 @@ test "std.zon add pointers" {
34954126 defer diag.deinit(gpa);
34964127 try std.testing.expectError(
34974128 error.ParseZon,
3498 fromSliceAlloc(*const ?*const f32, gpa, "true", &diag, .{}),
4129 fromSliceAlloc(*const ?*const f32, .{ .gpa = gpa, .source = "true", .diag = &diag }),
34994130 );
35004131 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
35014132 }
......@@ -3505,7 +4136,11 @@ test "std.zon add pointers" {
35054136 defer diag.deinit(gpa);
35064137 try std.testing.expectError(
35074138 error.ParseZon,
3508 fromSliceAlloc(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
4139 fromSliceAlloc(*const ?*const @Vector(3, u8), .{
4140 .gpa = gpa,
4141 .source = "true",
4142 .diag = &diag,
4143 }),
35094144 );
35104145 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{f}", .{diag});
35114146 }
......@@ -3515,7 +4150,7 @@ test "std.zon add pointers" {
35154150 defer diag.deinit(gpa);
35164151 try std.testing.expectError(
35174152 error.ParseZon,
3518 fromSliceAlloc(*const ?*const bool, gpa, "10", &diag, .{}),
4153 fromSliceAlloc(*const ?*const bool, .{ .gpa = gpa, .source = "10", .diag = &diag }),
35194154 );
35204155 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
35214156 }
......@@ -3525,7 +4160,7 @@ test "std.zon add pointers" {
35254160 defer diag.deinit(gpa);
35264161 try std.testing.expectError(
35274162 error.ParseZon,
3528 fromSliceAlloc(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
4163 fromSliceAlloc(*const ?*const struct { a: i32 }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35294164 );
35304165 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
35314166 }
......@@ -3535,7 +4170,7 @@ test "std.zon add pointers" {
35354170 defer diag.deinit(gpa);
35364171 try std.testing.expectError(
35374172 error.ParseZon,
3538 fromSliceAlloc(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
4173 fromSliceAlloc(*const ?*const struct { i32 }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35394174 );
35404175 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
35414176 }
......@@ -3545,7 +4180,7 @@ test "std.zon add pointers" {
35454180 defer diag.deinit(gpa);
35464181 try std.testing.expectError(
35474182 error.ParseZon,
3548 fromSliceAlloc(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
4183 fromSliceAlloc(*const ?*const union { x: void }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35494184 );
35504185 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
35514186 }
......@@ -3555,7 +4190,7 @@ test "std.zon add pointers" {
35554190 defer diag.deinit(gpa);
35564191 try std.testing.expectError(
35574192 error.ParseZon,
3558 fromSliceAlloc(*const ?*const [3]u8, gpa, "true", &diag, .{}),
4193 fromSliceAlloc(*const ?*const [3]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35594194 );
35604195 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
35614196 }
......@@ -3565,7 +4200,7 @@ test "std.zon add pointers" {
35654200 defer diag.deinit(gpa);
35664201 try std.testing.expectError(
35674202 error.ParseZon,
3568 fromSliceAlloc(?[3]u8, gpa, "true", &diag, .{}),
4203 fromSliceAlloc(?[3]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35694204 );
35704205 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
35714206 }
......@@ -3575,7 +4210,7 @@ test "std.zon add pointers" {
35754210 defer diag.deinit(gpa);
35764211 try std.testing.expectError(
35774212 error.ParseZon,
3578 fromSliceAlloc(*const ?*const []u8, gpa, "true", &diag, .{}),
4213 fromSliceAlloc(*const ?*const []u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35794214 );
35804215 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
35814216 }
......@@ -3585,7 +4220,7 @@ test "std.zon add pointers" {
35854220 defer diag.deinit(gpa);
35864221 try std.testing.expectError(
35874222 error.ParseZon,
3588 fromSliceAlloc(?[]u8, gpa, "true", &diag, .{}),
4223 fromSliceAlloc(?[]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35894224 );
35904225 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
35914226 }
......@@ -3595,7 +4230,7 @@ test "std.zon add pointers" {
35954230 defer diag.deinit(gpa);
35964231 try std.testing.expectError(
35974232 error.ParseZon,
3598 fromSliceAlloc(*const ?*const []const u8, gpa, "true", &diag, .{}),
4233 fromSliceAlloc(*const ?*const []const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
35994234 );
36004235 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
36014236 }
......@@ -3605,7 +4240,7 @@ test "std.zon add pointers" {
36054240 defer diag.deinit(gpa);
36064241 try std.testing.expectError(
36074242 error.ParseZon,
3608 fromSliceAlloc(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
4243 fromSliceAlloc(*const ?*const enum { foo }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
36094244 );
36104245 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
36114246 }
......@@ -3622,7 +4257,11 @@ test "std.zon stop on node" {
36224257
36234258 var diag: Diagnostics = .{};
36244259 defer diag.deinit(gpa);
3625 const result = try fromSlice(Vec2, gpa, ".{ .x = 1.5, .y = 2.5 }", &diag, .{});
4260 const result = try fromSlice(Vec2, .{
4261 .gpa = gpa,
4262 .source = ".{ .x = 1.5, .y = 2.5 }",
4263 .diag = &diag,
4264 });
36264265 try std.testing.expectEqual(result.y, 2.5);
36274266 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.5 }, result.x.get(diag.zoir));
36284267 }
......@@ -3630,7 +4269,11 @@ test "std.zon stop on node" {
36304269 {
36314270 var diag: Diagnostics = .{};
36324271 defer diag.deinit(gpa);
3633 const result = try fromSlice(Zoir.Node.Index, gpa, "1.23", &diag, .{});
4272 const result = try fromSlice(Zoir.Node.Index, .{
4273 .gpa = gpa,
4274 .source = "1.23",
4275 .diag = &diag,
4276 });
36344277 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(diag.zoir));
36354278 }
36364279}
......@@ -3640,7 +4283,11 @@ test "std.zon no alloc" {
36404283
36414284 try std.testing.expectEqual(
36424285 [3]u8{ 1, 2, 3 },
3643 try fromSlice([3]u8, gpa, ".{ 1, 2, 3 }", null, .{}),
4286 try fromSlice([3]u8, .{
4287 .gpa = gpa,
4288 .source = ".{ 1, 2, 3 }",
4289 .diag = null,
4290 }),
36444291 );
36454292
36464293 const Nested = struct { u8, u8, struct { u8, u8 } };
......@@ -3653,7 +4300,7 @@ test "std.zon no alloc" {
36534300
36544301 try std.testing.expectEqual(
36554302 Nested{ 1, 2, .{ 3, 4 } },
3656 try fromZoir(Nested, ast, zoir, .root, null, .{}),
4303 try fromZoir(Nested, .{ .ast = ast, .zoir = zoir, .diag = null }),
36574304 );
36584305}
36594306
......@@ -3665,19 +4312,35 @@ test "std.zon errors without diagnostics" {
36654312 bar,
36664313 baz,
36674314 };
3668 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Enum, gpa, ".nothing", null, .{}));
4315 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Enum, .{
4316 .gpa = gpa,
4317 .source = ".nothing",
4318 .diag = null,
4319 }));
36694320
36704321 const Struct = struct {
36714322 name: []const u8,
36724323 };
3673 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, gpa, ".{ .name = \"Alice\", .age = 25 }", null, .{}));
4324 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
4325 .gpa = gpa,
4326 .source = ".{ .name = \"Alice\", .age = 25 }",
4327 .diag = null,
4328 }));
36744329
36754330 const Union = union(enum) {
36764331 x,
36774332 y: u32,
36784333 };
3679 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".a", null, .{}));
3680 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".{ .b = 8 }", null, .{}));
4334 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
4335 .gpa = gpa,
4336 .source = ".a",
4337 .diag = null,
4338 }));
4339 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
4340 .gpa = gpa,
4341 .source = ".{ .b = 8 }",
4342 .diag = null,
4343 }));
36814344}
36824345
36834346test "std.zon aligned pointers" {
......@@ -3691,13 +4354,11 @@ test "std.zon aligned pointers" {
36914354 const expected: Foo = .{
36924355 .inner = &n,
36934356 };
3694 const found = try fromSliceAlloc(
3695 Foo,
3696 gpa,
3697 ".{ .inner = 10 }",
3698 null,
3699 .{},
3700 );
4357 const found = try fromSliceAlloc(Foo, .{
4358 .gpa = gpa,
4359 .source = ".{ .inner = 10 }",
4360 .diag = null,
4361 });
37014362 defer free(gpa, found);
37024363 try std.testing.expectEqualDeep(expected.inner, found.inner);
37034364}
......@@ -3743,94 +4404,78 @@ test "std.zon update" {
37434404 };
37444405 defer free(gpa, found);
37454406
3746 try updateFromSliceAlloc(
3747 MyStruct,
3748 gpa,
3749 &found,
3750 ".{}",
3751 null,
3752 .{},
3753 );
4407 try updateFromSliceAlloc(MyStruct, .{
4408 .gpa = gpa,
4409 .value = &found,
4410 .source = ".{}",
4411 .diag = null,
4412 });
37544413 try std.testing.expectEqualDeep(expected, found);
37554414
3756 try updateFromSliceAlloc(
3757 MyStruct,
3758 gpa,
3759 &found,
3760 ".{ .bar = false }",
3761 null,
3762 .{},
3763 );
4415 try updateFromSliceAlloc(MyStruct, .{
4416 .gpa = gpa,
4417 .value = &found,
4418 .source = ".{ .bar = false }",
4419 .diag = null,
4420 });
37644421 expected.bar = false;
37654422 try std.testing.expectEqualDeep(expected, found);
37664423
3767 try updateFromSliceAlloc(
3768 MyStruct,
3769 gpa,
3770 &found,
3771 ".{ .baz = .{ .a = .{ 2, 4 } } }",
3772 null,
3773 .{},
3774 );
4424 try updateFromSliceAlloc(MyStruct, .{
4425 .gpa = gpa,
4426 .value = &found,
4427 .source = ".{ .baz = .{ .a = .{ 2, 4 } } }",
4428 .diag = null,
4429 });
37754430 expected.baz.a[0] = 2;
37764431 expected.baz.a[1] = 4;
37774432 try std.testing.expectEqualDeep(expected, found);
37784433
3779 try updateFromSliceAlloc(
3780 MyStruct,
3781 gpa,
3782 &found,
3783 ".{ .foo = 11, .baz = .{ .b = .d } }",
3784 null,
3785 .{},
3786 );
4434 try updateFromSliceAlloc(MyStruct, .{
4435 .gpa = gpa,
4436 .value = &found,
4437 .source = ".{ .foo = 11, .baz = .{ .b = .d } }",
4438 .diag = null,
4439 });
37874440 expected.foo = 11;
37884441 expected.baz.b = .d;
37894442 try std.testing.expectEqualDeep(expected, found);
37904443
3791 try updateFromSliceAlloc(
3792 MyStruct,
3793 gpa,
3794 &found,
3795 ".{ .optional = 10 }",
3796 null,
3797 .{},
3798 );
4444 try updateFromSliceAlloc(MyStruct, .{
4445 .gpa = gpa,
4446 .value = &found,
4447 .source = ".{ .optional = 10 }",
4448 .diag = null,
4449 });
37994450 expected.optional = 10;
38004451 try std.testing.expectEqualDeep(expected, found);
38014452
3802 try updateFromSliceAlloc(
3803 MyStruct,
3804 gpa,
3805 &found,
3806 ".{ .optional = null }",
3807 null,
3808 .{},
3809 );
4453 try updateFromSliceAlloc(MyStruct, .{
4454 .gpa = gpa,
4455 .value = &found,
4456 .source = ".{ .optional = null }",
4457 .diag = null,
4458 });
38104459 expected.optional = null;
38114460 try std.testing.expectEqualDeep(expected, found);
38124461
3813 try updateFromSliceAlloc(
3814 MyStruct,
3815 gpa,
3816 &found,
3817 ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",
3818 null,
3819 .{},
3820 );
4462 try updateFromSliceAlloc(MyStruct, .{
4463 .gpa = gpa,
4464 .value = &found,
4465 .source = ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",
4466 .diag = null,
4467 });
38214468 expected.ptr.x = 10;
38224469 expected.ptr.y = 20;
38234470 expected.ptr.z = 30;
38244471 try std.testing.expectEqualDeep(expected, found);
38254472
3826 try updateFromSliceAlloc(
3827 MyStruct,
3828 gpa,
3829 &found,
3830 ".{ .str = \"foo\" }",
3831 null,
3832 .{},
3833 );
4473 try updateFromSliceAlloc(MyStruct, .{
4474 .gpa = gpa,
4475 .value = &found,
4476 .source = ".{ .str = \"foo\" }",
4477 .diag = null,
4478 });
38344479 gpa.free(expected.str);
38354480 expected.str = gpa.dupe(u8, "foo") catch @panic("oom");
38364481 try std.testing.expectEqualDeep(expected, found);
......@@ -3854,19 +4499,40 @@ test "std.zon variants" {
38544499 defer zoir.deinit(gpa);
38554500
38564501 var curr = start;
3857 try updateFromSlice(Struct, gpa, &curr, ".{ .a = 100 }", null, .{});
4502 try updateFromSlice(Struct, .{
4503 .gpa = gpa,
4504 .value = &curr,
4505 .source = ".{ .a = 100 }",
4506 .diag = null,
4507 });
38584508 try std.testing.expectEqual(end, curr);
38594509
38604510 curr = start;
3861 try updateFromSliceAlloc(Struct, gpa, &curr, ".{ .a = 100 }", null, .{});
4511 try updateFromSliceAlloc(Struct, .{
4512 .gpa = gpa,
4513 .value = &curr,
4514 .source = ".{ .a = 100 }",
4515 .diag = null,
4516 });
38624517 try std.testing.expectEqual(end, curr);
38634518
38644519 curr = start;
3865 try updateFromZoir(Struct, &curr, ast, zoir, .root, null, .{});
4520 try updateFromZoir(Struct, .{
4521 .ast = ast,
4522 .value = &curr,
4523 .zoir = zoir,
4524 .diag = null,
4525 });
38664526 try std.testing.expectEqual(end, curr);
38674527
38684528 curr = start;
3869 try updateFromZoirAlloc(Struct, gpa, &curr, ast, zoir, .root, null, .{});
4529 try updateFromZoirAlloc(Struct, .{
4530 .gpa = gpa,
4531 .value = &curr,
4532 .ast = ast,
4533 .zoir = zoir,
4534 .diag = null,
4535 });
38704536 try std.testing.expectEqual(end, curr);
38714537 }
38724538
......@@ -3879,18 +4545,35 @@ test "std.zon variants" {
38794545
38804546 try std.testing.expectEqual(
38814547 end,
3882 try fromSlice(Struct, gpa, ".{ .a = 100, .b = 20 }", null, .{}),
4548 try fromSlice(Struct, .{
4549 .gpa = gpa,
4550 .source = ".{ .a = 100, .b = 20 }",
4551 .diag = null,
4552 }),
38834553 );
38844554 try std.testing.expectEqual(
38854555 end,
3886 try fromSliceAlloc(Struct, gpa, ".{ .a = 100, .b = 20 }", null, .{}),
4556 try fromSliceAlloc(Struct, .{
4557 .gpa = gpa,
4558 .source = ".{ .a = 100, .b = 20 }",
4559 .diag = null,
4560 }),
38874561 );
38884562 try std.testing.expectEqual(
3889 try fromZoir(Struct, ast, zoir, .root, null, .{}),
4563 try fromZoir(Struct, .{
4564 .ast = ast,
4565 .zoir = zoir,
4566 .diag = null,
4567 }),
38904568 end,
38914569 );
38924570 try std.testing.expectEqual(
3893 try fromZoirAlloc(Struct, gpa, ast, zoir, .root, null, .{}),
4571 try fromZoirAlloc(Struct, .{
4572 .gpa = gpa,
4573 .ast = ast,
4574 .zoir = zoir,
4575 .diag = null,
4576 }),
38944577 end,
38954578 );
38964579 }