authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-07-20 17:14:44-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-09-26 12:35:38-07:00
loged70c643492c7c49057a72ff3e1981cb1ca81e57
tree0e297668f0c10968588f99b35ffa366bab8db149
parent07149649ce9201399233628d2dea61ebb061c430

Use arena for diagnostics and results


4 files changed, 909 insertions(+), 1027 deletions(-)

lib/std/zig/ErrorBundle.zig+2-2
...@@ -631,7 +631,7 @@ pub const Wip = struct {...@@ -631,7 +631,7 @@ pub const Wip = struct {
631 const err_loc = std.zig.findLineColumn(source, err_span.main);631 const err_loc = std.zig.findLineColumn(source, err_span.main);
632632
633 try eb.addRootErrorMessage(.{633 try eb.addRootErrorMessage(.{
634 .msg = try eb.addString(err.msg.get(zoir)),634 .msg = try eb.addString(err.msg.get(&zoir)),
635 .src_loc = try eb.addSourceLocation(.{635 .src_loc = try eb.addSourceLocation(.{
636 .src_path = try eb.addString(src_path),636 .src_path = try eb.addString(src_path),
637 .span_start = err_span.start,637 .span_start = err_span.start,
...@@ -661,7 +661,7 @@ pub const Wip = struct {...@@ -661,7 +661,7 @@ pub const Wip = struct {
661661
662 // This line can cause `wip.extra.items` to be resized.662 // This line can cause `wip.extra.items` to be resized.
663 const note_index = @backingInt(try eb.addErrorMessage(.{663 const note_index = @backingInt(try eb.addErrorMessage(.{
664 .msg = try eb.addString(note.msg.get(zoir)),664 .msg = try eb.addString(note.msg.get(&zoir)),
665 .src_loc = try eb.addSourceLocation(.{665 .src_loc = try eb.addSourceLocation(.{
666 .src_path = try eb.addString(src_path),666 .src_path = try eb.addString(src_path),
667 .span_start = note_span.start,667 .span_start = note_span.start,
lib/std/zig/Zoir.zig+6-6
...@@ -42,7 +42,7 @@ pub const Header = extern struct {...@@ -42,7 +42,7 @@ pub const Header = extern struct {
42 }42 }
43};43};
4444
45pub fn hasCompileErrors(zoir: Zoir) bool {45pub fn hasCompileErrors(zoir: *const Zoir) bool {
46 if (zoir.compile_errors.len > 0) {46 if (zoir.compile_errors.len > 0) {
47 assert(zoir.nodes.len == 0);47 assert(zoir.nodes.len == 0);
48 assert(zoir.extra.len == 0);48 assert(zoir.extra.len == 0);
...@@ -54,7 +54,7 @@ pub fn hasCompileErrors(zoir: Zoir) bool {...@@ -54,7 +54,7 @@ pub fn hasCompileErrors(zoir: Zoir) bool {
54 }54 }
55}55}
5656
57pub fn deinit(zoir: Zoir, gpa: Allocator) void {57pub fn deinit(zoir: *const Zoir, gpa: Allocator) void {
58 var nodes = zoir.nodes;58 var nodes = zoir.nodes;
59 nodes.deinit(gpa);59 nodes.deinit(gpa);
6060
...@@ -105,7 +105,7 @@ pub const Node = union(enum) {...@@ -105,7 +105,7 @@ pub const Node = union(enum) {
105 root = 0,105 root = 0,
106 _,106 _,
107107
108 pub fn get(idx: Index, zoir: Zoir) Node {108 pub fn get(idx: Index, zoir: *const Zoir) Node {
109 const repr = zoir.nodes.get(@backingInt(idx));109 const repr = zoir.nodes.get(@backingInt(idx));
110 return switch (repr.tag) {110 return switch (repr.tag) {
111 .true => .true,111 .true => .true,
...@@ -151,7 +151,7 @@ pub const Node = union(enum) {...@@ -151,7 +151,7 @@ pub const Node = union(enum) {
151 };151 };
152 }152 }
153153
154 pub fn getAstNode(idx: Index, zoir: Zoir) std.zig.Ast.Node.Index {154 pub fn getAstNode(idx: Index, zoir: *const Zoir) std.zig.Ast.Node.Index {
155 return zoir.nodes.items(.ast_node)[@backingInt(idx)];155 return zoir.nodes.items(.ast_node)[@backingInt(idx)];
156 }156 }
157157
...@@ -227,7 +227,7 @@ pub const Node = union(enum) {...@@ -227,7 +227,7 @@ pub const Node = union(enum) {
227227
228pub const NullTerminatedString = enum(u32) {228pub const NullTerminatedString = enum(u32) {
229 _,229 _,
230 pub fn get(nts: NullTerminatedString, zoir: Zoir) [:0]const u8 {230 pub fn get(nts: NullTerminatedString, zoir: *const Zoir) [:0]const u8 {
231 const idx = std.mem.findScalar(u8, zoir.string_bytes[@backingInt(nts)..], 0).?;231 const idx = std.mem.findScalar(u8, zoir.string_bytes[@backingInt(nts)..], 0).?;
232 return zoir.string_bytes[@backingInt(nts)..][0..idx :0];232 return zoir.string_bytes[@backingInt(nts)..][0..idx :0];
233 }233 }
...@@ -244,7 +244,7 @@ pub const CompileError = extern struct {...@@ -244,7 +244,7 @@ pub const CompileError = extern struct {
244 first_note: u32,244 first_note: u32,
245 note_count: u32,245 note_count: u32,
246246
247 pub fn getNotes(err: CompileError, zoir: Zoir) []const Note {247 pub fn getNotes(err: CompileError, zoir: *const Zoir) []const Note {
248 return zoir.error_notes[err.first_note..][0..err.note_count];248 return zoir.error_notes[err.first_note..][0..err.note_count];
249 }249 }
250250
lib/std/zig/ZonGen.zig+4-4
...@@ -490,7 +490,7 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) error{ OutOfMemory,...@@ -490,7 +490,7 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) error{ OutOfMemory,
490}490}
491491
492/// Estimates the size of a string node without parsing it.492/// Estimates the size of a string node without parsing it.
493pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {493pub fn strLitSizeHint(tree: *const Ast, node: Ast.Node.Index) usize {
494 switch (tree.nodeTag(node)) {494 switch (tree.nodeTag(node)) {
495 // Parsed string literals are typically around the size of the raw strings.495 // Parsed string literals are typically around the size of the raw strings.
496 .string_literal => {496 .string_literal => {
...@@ -515,7 +515,7 @@ pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {...@@ -515,7 +515,7 @@ pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
515515
516/// Parses the given node as a string literal.516/// Parses the given node as a string literal.
517pub fn parseStrLit(517pub fn parseStrLit(
518 tree: Ast,518 tree: *const Ast,
519 node: Ast.Node.Index,519 node: Ast.Node.Index,
520 writer: *Writer,520 writer: *Writer,
521) Writer.Error!std.zig.string_literal.Result {521) Writer.Error!std.zig.string_literal.Result {
...@@ -559,12 +559,12 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) error{ OutOfMemory, Bad...@@ -559,12 +559,12 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) error{ OutOfMemory, Bad
559 const gpa = zg.gpa;559 const gpa = zg.gpa;
560 const string_bytes = &zg.string_bytes;560 const string_bytes = &zg.string_bytes;
561 const str_index: u32 = @intCast(zg.string_bytes.items.len);561 const str_index: u32 = @intCast(zg.string_bytes.items.len);
562 const size_hint = strLitSizeHint(zg.tree, str_node);562 const size_hint = strLitSizeHint(&zg.tree, str_node);
563 try string_bytes.ensureUnusedCapacity(gpa, size_hint);563 try string_bytes.ensureUnusedCapacity(gpa, size_hint);
564 const result = r: {564 const result = r: {
565 var aw: Writer.Allocating = .fromArrayList(gpa, &zg.string_bytes);565 var aw: Writer.Allocating = .fromArrayList(gpa, &zg.string_bytes);
566 defer zg.string_bytes = aw.toArrayList();566 defer zg.string_bytes = aw.toArrayList();
567 break :r parseStrLit(zg.tree, str_node, &aw.writer) catch |err| switch (err) {567 break :r parseStrLit(&zg.tree, str_node, &aw.writer) catch |err| switch (err) {
568 error.WriteFailed => return error.OutOfMemory,568 error.WriteFailed => return error.OutOfMemory,
569 };569 };
570 };570 };
lib/std/zon/parse.zig+897-1015
...@@ -1,13 +1,11 @@...@@ -1,13 +1,11 @@
1//! The simplest way to parse ZON at runtime is to use `fromSlice`/`fromSliceAlloc`.1//! The simplest way to parse ZON at runtime is to use `fromSlice`/`fromSliceAlloc`.
2//!2//!
3//! Note that if you need to parse ZON at compile time, you may use `@import`.
4//!
5//! Parsing from individual Zoir nodes is also available:3//! Parsing from individual Zoir nodes is also available:
6//! * `fromZoir`/`fromZoirAlloc`4//! * `fromZoir`/`fromZoirAlloc`
7//!5//!
8//! To update an existing values, see the `updateFrom*` variants.6//! To update an existing values, see the `updateFrom*` variants. To get human readable errors, use
9//!7//! the `diag` option. For lower level control over parsing, see `std.zig.Zoir`. For importing ZON
10//! For lower level control over parsing, see `std.zig.Zoir`.8//! at compile time, use `@import`.
119
12const std = @import("std");10const std = @import("std");
13const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
...@@ -20,235 +18,122 @@ const StrLitErr = std.zig.string_literal.Error;...@@ -20,235 +18,122 @@ const StrLitErr = std.zig.string_literal.Error;
20const NumberLiteralError = std.zig.number_literal.Error;18const NumberLiteralError = std.zig.number_literal.Error;
21const assert = std.debug.assert;19const assert = std.debug.assert;
22const ArrayList = std.ArrayList;20const ArrayList = std.ArrayList;
21const ArenaAllocator = std.heap.ArenaAllocator;
2322
24/// Rename when adding or removing support for a type.23/// Rename when adding or removing support for a type.
25const valid_types = {};24const valid_types = {};
2625
27pub const Error = union(enum) {26pub const Error = struct {
28 zoir: Zoir.CompileError,27 msg: []const u8,
29 type_check: Error.TypeCheckFailure,28 loc: Ast.Location,
3029 token: Ast.OptionalTokenIndex,
31 pub const Note = union(enum) {30 /// If `token == .none`, this is an `Ast.Node.Index`.
32 zoir: Zoir.CompileError.Note,31 /// Otherwise, this is a byte offset into `token`.
33 type_check: TypeCheckFailure.Note,32 node_or_offset: u32,
3433 notes: []Note,
35 pub const Iterator = struct {34
36 index: usize = 0,35 const InitOptions = struct {
37 err: Error,36 msg: []const u8,
38 diag: *const Diagnostics,37 token: Ast.OptionalTokenIndex,
3938 node_or_offset: u32,
40 pub fn next(self: *@This()) ?Note {39 notes: []Note,
41 switch (self.err) {
42 .zoir => |err| {
43 if (self.index >= err.note_count) return null;
44 const note = err.getNotes(self.diag.zoir)[self.index];
45 self.index += 1;
46 return .{ .zoir = note };
47 },
48 .type_check => |err| {
49 if (self.index >= err.getNoteCount()) return null;
50 const note = err.getNote(self.index);
51 self.index += 1;
52 return .{ .type_check = note };
53 },
54 }
55 }
56 };
57
58 fn formatMessage(self: []const u8, w: *std.Io.Writer) std.Io.Writer.Error!void {
59 // Just writes the string for now, but we're keeping this behind a formatter so we have
60 // the option to extend it in the future to print more advanced messages (like `Error`
61 // does) without breaking the API.
62 try w.writeAll(self);
63 }
64
65 pub fn fmtMessage(self: Note, diag: *const Diagnostics) std.fmt.Alt([]const u8, Note.formatMessage) {
66 return .{ .data = switch (self) {
67 .zoir => |note| note.msg.get(diag.zoir),
68 .type_check => |note| note.msg,
69 } };
70 }
71
72 pub fn getLocation(self: Note, diag: *const Diagnostics) Ast.Location {
73 switch (self) {
74 .zoir => |note| return zoirErrorLocation(diag.ast, note.token, note.node_or_offset),
75 .type_check => |note| return diag.ast.tokenLocation(note.offset, note.token),
76 }
77 }
78 };40 };
7941
80 pub const Iterator = struct {42 fn init(ast: *const Ast, options: InitOptions) @This() {
81 index: usize = 0,43 return .{
82 diag: *const Diagnostics,44 .msg = options.msg,
8345 .loc = astLoc(ast, options.token, options.node_or_offset),
84 pub fn next(self: *@This()) ?Error {46 .token = options.token,
85 if (self.index < self.diag.zoir.compile_errors.len) {47 .node_or_offset = options.node_or_offset,
86 const result: Error = .{ .zoir = self.diag.zoir.compile_errors[self.index] };48 .notes = options.notes,
87 self.index += 1;
88 return result;
89 }
90
91 if (self.diag.type_check) |err| {
92 if (self.index == self.diag.zoir.compile_errors.len) {
93 const result: Error = .{ .type_check = err };
94 self.index += 1;
95 return result;
96 }
97 }
98
99 return null;
100 }
101 };
102
103 const TypeCheckFailure = struct {
104 const Note = struct {
105 token: Ast.TokenIndex,
106 offset: u32,
107 msg: []const u8,
108 owned: bool,
109
110 fn deinit(self: @This(), gpa: Allocator) void {
111 if (self.owned) gpa.free(self.msg);
112 }
113 };49 };
114
115 message: []const u8,
116 owned: bool,
117 token: Ast.TokenIndex,
118 offset: u32,
119 note: ?@This().Note,
120
121 fn deinit(self: @This(), gpa: Allocator) void {
122 if (self.note) |note| note.deinit(gpa);
123 if (self.owned) gpa.free(self.message);
124 }
125
126 fn getNoteCount(self: @This()) usize {
127 return @intFromBool(self.note != null);
128 }
129
130 fn getNote(self: @This(), index: usize) @This().Note {
131 assert(index == 0);
132 return self.note.?;
133 }
134 };
135
136 const FormatMessage = struct {
137 err: Error,
138 diag: *const Diagnostics,
139 };
140
141 fn formatMessage(self: FormatMessage, w: *std.Io.Writer) std.Io.Writer.Error!void {
142 switch (self.err) {
143 .zoir => |err| try w.writeAll(err.msg.get(self.diag.zoir)),
144 .type_check => |tc| try w.writeAll(tc.message),
145 }
146 }
147
148 pub fn fmtMessage(self: @This(), diag: *const Diagnostics) std.fmt.Alt(FormatMessage, formatMessage) {
149 return .{ .data = .{
150 .err = self,
151 .diag = diag,
152 } };
153 }
154
155 pub fn getLocation(self: @This(), diag: *const Diagnostics) Ast.Location {
156 return switch (self) {
157 .zoir => |err| return zoirErrorLocation(
158 diag.ast,
159 err.token,
160 err.node_or_offset,
161 ),
162 .type_check => |err| return diag.ast.tokenLocation(err.offset, err.token),
163 };
164 }
165
166 pub fn iterateNotes(self: @This(), diag: *const Diagnostics) Note.Iterator {
167 return .{ .err = self, .diag = diag };
168 }50 }
16951
170 fn zoirErrorLocation(ast: Ast, maybe_token: Ast.OptionalTokenIndex, node_or_offset: u32) Ast.Location {52 fn astLoc(
53 ast: *const Ast,
54 maybe_token: Ast.OptionalTokenIndex,
55 node_or_offset: u32,
56 ) Ast.Location {
171 if (maybe_token.unwrap()) |token| {57 if (maybe_token.unwrap()) |token| {
172 var location = ast.tokenLocation(0, token);58 var loc = ast.tokenLocation(0, token);
173 location.column += node_or_offset;59 loc.column += node_or_offset;
174 return location;60 return loc;
175 } else {61 } else {
176 const ast_node: Ast.Node.Index = @fromBackingInt(@intCast(node_or_offset));62 const ast_node: Ast.Node.Index = @fromBackingInt(@intCast(node_or_offset));
177 const token = ast.nodeMainToken(ast_node);63 const token = ast.nodeMainToken(ast_node);
178 return ast.tokenLocation(0, token);64 return ast.tokenLocation(0, token);
179 }65 }
180 }66 }
67
68 pub const Note = struct {
69 msg: []const u8,
70 loc: Ast.Location,
71 token: Ast.OptionalTokenIndex,
72 /// If `token == .none`, this is an `Ast.Node.Index`.
73 /// Otherwise, this is a byte offset into `token`.
74 node_or_offset: u32,
75
76 const InitOptions = struct {
77 msg: []const u8,
78 token: Ast.OptionalTokenIndex,
79 node_or_offset: u32,
80 };
81
82 fn init(ast: *const Ast, options: @This().InitOptions) @This() {
83 return .{
84 .msg = options.msg,
85 .loc = astLoc(ast, options.token, options.node_or_offset),
86 .token = options.token,
87 .node_or_offset = options.node_or_offset,
88 };
89 }
90 };
181};91};
18292
183/// Information about the success or failure of a parse.93/// Human readable information about the success or failure of a parse.
184pub const Diagnostics = struct {94pub const Diagnostics = struct {
185 ast: Ast = .{95 arena: Allocator,
186 .source = "",96 compile_errors: std.ArrayList(Error),
187 .tokens = .empty,97
188 .nodes = .empty,98 pub fn init(arena: Allocator) @This() {
189 .extra_data = &.{},99 return .{
190 .mode = .zon,100 .arena = arena,
191 .errors = &.{},101 .compile_errors = .empty,
192 },102 };
193 zoir: Zoir = .{
194 .nodes = .empty,
195 .extra = &.{},
196 .limbs = &.{},
197 .string_bytes = &.{},
198 .compile_errors = &.{},
199 .error_notes = &.{},
200 },
201 type_check: ?Error.TypeCheckFailure = null,
202
203 fn assertEmpty(self: Diagnostics) void {
204 assert(self.ast.tokens.len == 0);
205 assert(self.zoir.nodes.len == 0);
206 assert(self.type_check == null);
207 }
208
209 pub fn deinit(self: *Diagnostics, gpa: Allocator) void {
210 self.ast.deinit(gpa);
211 self.zoir.deinit(gpa);
212 if (self.type_check) |tc| tc.deinit(gpa);
213 self.* = undefined;
214 }
215
216 pub fn iterateErrors(self: *const Diagnostics) Error.Iterator {
217 return .{ .diag = self };
218 }103 }
219104
220 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {105 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
221 var errors = self.iterateErrors();106 for (self.compile_errors.items) |e| {
222 while (errors.next()) |err| {107 try w.print("{d}:{d}: error: {s}\n", .{
223 const loc = err.getLocation(self);108 e.loc.line + 1,
224 const msg = err.fmtMessage(self);109 e.loc.column + 1,
225 try w.print("{d}:{d}: error: {f}\n", .{ loc.line + 1, loc.column + 1, msg });110 e.msg,
226111 });
227 var notes = err.iterateNotes(self);112
228 while (notes.next()) |note| {113 for (e.notes) |note| {
229 const note_loc = note.getLocation(self);114 try w.print("{d}:{d}: note: {s}\n", .{
230 const note_msg = note.fmtMessage(self);115 note.loc.line + 1,
231 try w.print("{d}:{d}: note: {f}\n", .{116 note.loc.column + 1,
232 note_loc.line + 1,117 note.msg,
233 note_loc.column + 1,
234 note_msg,
235 });118 });
236 }119 }
237 }120 }
238 }121 }
122
123 pub fn clear(self: *@This()) void {
124 self.compile_errors.clearRetainingCapacity();
125 }
239};126};
240127
241pub const FromSliceOptions = struct {128pub const FromSliceOptions = struct {
129 /// Used for scratch allocations.
242 gpa: Allocator,130 gpa: Allocator,
131 /// The ZON source.
243 source: [:0]const u8,132 source: [:0]const u8,
244 /// Write human readable error messages here.133 /// Write human readable error messages here.
245 diag: ?*Diagnostics,134 diag: ?*Diagnostics,
246 /// If true, unknown fields do not error.135 /// If true, unknown fields do not error.
247 ignore_unknown_fields: bool = false,136 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};137};
253138
254/// Parses the given slice as ZON.139/// Parses the given slice as ZON.
...@@ -257,7 +142,7 @@ pub const FromSliceOptions = struct {...@@ -257,7 +142,7 @@ pub const FromSliceOptions = struct {
257/// invalid or can not be deserialized into type `T`.142/// invalid or can not be deserialized into type `T`.
258///143///
259/// When the parser returns `error.ParseZon`, it will also store a human readable explanation in144/// When the parser returns `error.ParseZon`, it will also store a human readable explanation in
260/// `diag` if non null. If diag is not null, it must be initialized to `.{}`.145/// `diag` if non null.
261///146///
262/// Asserts at compile time that the result type doesn't contain pointers. As such, the result147/// Asserts at compile time that the result type doesn't contain pointers. As such, the result
263/// doesn't need to be freed.148/// doesn't need to be freed.
...@@ -265,25 +150,13 @@ pub const FromSliceOptions = struct {...@@ -265,25 +150,13 @@ pub const FromSliceOptions = struct {
265/// An allocator is still required for temporary allocations made during parsing.150/// An allocator is still required for temporary allocations made during parsing.
266pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {151pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
267 comptime assert(!requiresAllocator(T));152 comptime assert(!requiresAllocator(T));
268 return fromSliceAlloc(T, options);153 return fromSliceAlloc(T, .{
269}154 .gpa = options.gpa,
270155 .arena = .failing,
271pub fn UpdateFromSliceOptions(T: type) type {156 .source = options.source,
272 return struct {157 .diag = options.diag,
273 gpa: Allocator,158 .ignore_unknown_fields = options.ignore_unknown_fields,
274 /// The value to update.159 });
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 };
287}160}
288161
289/// Similar to `fromSlice`, but updates an existing value `current`. Fields not specified by ZON are162/// Similar to `fromSlice`, but updates an existing value `current`. Fields not specified by ZON are
...@@ -291,141 +164,139 @@ pub fn UpdateFromSliceOptions(T: type) type {...@@ -291,141 +164,139 @@ pub fn UpdateFromSliceOptions(T: type) type {
291/// failure, values that were updated prior to the failure are left updated.164/// failure, values that were updated prior to the failure are left updated.
292pub fn updateFromSlice(165pub fn updateFromSlice(
293 T: type,166 T: type,
294 options: UpdateFromSliceOptions(T),167 value: *T,
168 options: FromSliceOptions,
295) error{ OutOfMemory, ParseZon }!void {169) error{ OutOfMemory, ParseZon }!void {
296 comptime assert(!requiresAllocator(T));170 comptime assert(!requiresAllocator(T));
297 try updateFromSliceAlloc(T, options);171 try updateFromSliceAlloc(T, value, .{
172 .gpa = options.gpa,
173 .arena = .failing,
174 .source = options.source,
175 .diag = options.diag,
176 .ignore_unknown_fields = options.ignore_unknown_fields,
177 });
298}178}
299179
300pub const FromSliceAllocOptions = FromSliceOptions;180pub const FromSliceAllocOptions = struct {
181 /// Used for scratch allocations.
182 gpa: Allocator,
183 /// Owns the result.
184 arena: Allocator,
185 /// The ZON source.
186 source: [:0]const u8,
187 /// Write human readable error messages here.
188 diag: ?*Diagnostics,
189 /// If true, unknown fields do not error.
190 ignore_unknown_fields: bool = false,
191};
301192
302/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see193/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see
303/// `free`.194/// `free`.
304pub fn fromSliceAlloc(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {195pub fn fromSliceAlloc(T: type, options: FromSliceAllocOptions) error{ OutOfMemory, ParseZon }!T {
305 var result: T = undefined;196 var value: T = undefined;
306 try parseSliceAlloc(T, &result, options.gpa, options.source, options.diag, .{197 try parseSliceAlloc(T, &value, .{
307 .ignore_unknown_fields = options.ignore_unknown_fields,198 .gpa = options.gpa,
308 .ignore_missing_fields = false,199 .arena = options.arena,
309 .free_on_error = options.free_on_error,200 .source = options.source,
310 .free_on_write = false,201 .diag = options.diag,
202 .parser_options = .{
203 .ignore_unknown_fields = options.ignore_unknown_fields,
204 .ignore_missing_fields = false,
205 },
311 });206 });
312 return result;207 return value;
313}208}
314209
315pub const UpdateFromSliceAllocOptions = UpdateFromSliceOptions;
316
317/// Like updateFromSlice`, but the result may contain pointers.210/// Like updateFromSlice`, but the result may contain pointers.
318pub fn updateFromSliceAlloc(211pub fn updateFromSliceAlloc(
319 T: type,212 T: type,
320 options: UpdateFromSliceAllocOptions(T),213 value: *T,
214 options: FromSliceAllocOptions,
321) error{ OutOfMemory, ParseZon }!void {215) error{ OutOfMemory, ParseZon }!void {
322 try parseSliceAlloc(216 try parseSliceAlloc(T, value, .{
323 T,217 .gpa = options.gpa,
324 options.value,218 .arena = options.arena,
325 options.gpa,219 .source = options.source,
326 options.source,220 .diag = options.diag,
327 options.diag,221 .parser_options = .{
328 .{
329 .ignore_unknown_fields = options.ignore_unknown_fields,222 .ignore_unknown_fields = options.ignore_unknown_fields,
330 .ignore_missing_fields = true,223 .ignore_missing_fields = true,
331 .free_on_error = false,
332 .free_on_write = options.free_on_write,
333 },224 },
334 );225 });
335}226}
336227
337fn parseSliceAlloc(228const ParseSliceAllocOptions = struct {
338 T: type,
339 out: *T,
340 gpa: Allocator,229 gpa: Allocator,
230 arena: Allocator,
341 source: [:0]const u8,231 source: [:0]const u8,
342 diag: ?*Diagnostics,232 diag: ?*Diagnostics,
343 options: Parser.Options,233 parser_options: Parser.Options,
344) error{ OutOfMemory, ParseZon }!void {234};
345 if (diag) |s| s.assertEmpty();
346235
347 var ast = try std.zig.Ast.parse(gpa, source, .{ .mode = .zon });236fn parseSliceAlloc(
348 defer if (diag == null) ast.deinit(gpa);237 T: type,
349 if (diag) |s| s.ast = ast;238 value: *T,
239 options: ParseSliceAllocOptions,
240) error{ OutOfMemory, ParseZon }!void {
241 var ast = try std.zig.Ast.parse(options.gpa, options.source, .{ .mode = .zon });
242 defer ast.deinit(options.gpa);
350243
351 // If there's no diagnostics, Zoir exists for the lifetime of this function. If there is a244 var zoir = try ZonGen.generate(options.gpa, ast, .{ .parse_str_lits = false });
352 // diagnostics, ownership is transferred to diagnostics.245 defer zoir.deinit(options.gpa);
353 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
354 defer if (diag == null) zoir.deinit(gpa);
355246
356 if (diag) |s| s.* = .{};247 try parseZoirAlloc(T, value, .{
357 try parseZoirAlloc(T, out, gpa, ast, zoir, .root, diag, options);248 .arena = options.arena,
249 .ast = &ast,
250 .zoir = &zoir,
251 .node = .root,
252 .diag = options.diag,
253 .parser_options = options.parser_options,
254 });
358}255}
359256
360pub const FromZoirOptions = struct {257pub const FromZoirOptions = struct {
361 /// The AST for this this ZON value.258 /// The AST for this this ZON value.
362 ast: Ast,259 ast: *const Ast,
363 /// The zig object intermediate representation of this ZON value.260 /// The zig object intermediate representation of this ZON value.
364 zoir: Zoir,261 zoir: *const Zoir,
365 /// The node to start parsing at.262 /// The node to start parsing at.
366 node: Zoir.Node.Index = .root,263 node: Zoir.Node.Index = .root,
367 /// Write human readable error messages here.264 /// Write human readable error messages here.
368 diag: ?*Diagnostics,265 diag: ?*Diagnostics,
369 /// If true, unknown fields do not error.266 /// If true, unknown fields do not error.
370 ignore_unknown_fields: bool = false,267 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};268};
376269
377/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.270/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
378pub fn fromZoir(T: type, options: FromZoirOptions) error{ParseZon}!T {271pub fn fromZoir(T: type, options: FromZoirOptions) error{ParseZon}!T {
379 comptime assert(!requiresAllocator(T));272 comptime assert(!requiresAllocator(T));
380 return fromZoirAlloc(T, .{273 return fromZoirAlloc(T, .{
381 .gpa = .failing,274 .arena = .failing,
382 .ast = options.ast,275 .ast = options.ast,
383 .zoir = options.zoir,276 .zoir = options.zoir,
384 .node = options.node,277 .node = options.node,
385 .diag = options.diag,278 .diag = options.diag,
386 .ignore_unknown_fields = options.ignore_unknown_fields,279 .ignore_unknown_fields = options.ignore_unknown_fields,
387 .free_on_error = options.free_on_error,
388 }) catch |err| switch (err) {280 }) catch |err| switch (err) {
389 error.OutOfMemory => unreachable, // Checked by comptime assertion above281 error.OutOfMemory => unreachable, // Checked by comptime assertion above
390 else => |e| return e,282 else => |e| return e,
391 };283 };
392}284}
393285
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
414/// Like `updateSlice`, but operates on `Zoir` instead of ZON source.286/// Like `updateSlice`, but operates on `Zoir` instead of ZON source.
415pub fn updateFromZoir(287pub fn updateFromZoir(
416 T: type,288 T: type,
417 options: UpdateFromZoirOptions(T),289 value: *T,
290 options: FromZoirOptions,
418) error{ParseZon}!void {291) error{ParseZon}!void {
419 comptime assert(!requiresAllocator(T));292 comptime assert(!requiresAllocator(T));
420 updateFromZoirAlloc(T, .{293 updateFromZoirAlloc(T, value, .{
421 .gpa = .failing,294 .arena = .failing,
422 .value = options.value,
423 .ast = options.ast,295 .ast = options.ast,
424 .zoir = options.zoir,296 .zoir = options.zoir,
425 .node = options.node,297 .node = options.node,
426 .diag = options.diag,298 .diag = options.diag,
427 .ignore_unknown_fields = options.ignore_unknown_fields,299 .ignore_unknown_fields = options.ignore_unknown_fields,
428 .free_on_write = options.free_on_write,
429 }) catch |err| switch (err) {300 }) catch |err| switch (err) {
430 error.OutOfMemory => unreachable, // Checked by comptime assertion above301 error.OutOfMemory => unreachable, // Checked by comptime assertion above
431 else => |e| return e,302 else => |e| return e,
...@@ -433,172 +304,103 @@ pub fn updateFromZoir(...@@ -433,172 +304,103 @@ pub fn updateFromZoir(
433}304}
434305
435pub const FromZoirAllocOptions = struct {306pub const FromZoirAllocOptions = struct {
436 gpa: Allocator,307 /// Owns the result.
308 arena: Allocator,
437 /// The AST for this ZON value.309 /// The AST for this ZON value.
438 ast: Ast,310 ast: *const Ast,
439 /// The zig object intermediate representation of this ZON value.311 /// The zig object intermediate representation of this ZON value.
440 zoir: Zoir,312 zoir: *const Zoir,
441 /// The node to start parsing at.313 /// The node to start parsing at.
442 node: Zoir.Node.Index = .root,314 node: Zoir.Node.Index = .root,
443 /// Write human readable error messages here.315 /// Write human readable error messages here.
444 diag: ?*Diagnostics,316 diag: ?*Diagnostics,
445 /// If true, unknown fields do not error.317 /// If true, unknown fields do not error.
446 ignore_unknown_fields: bool = false,318 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};319};
452320
453/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.321/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
454pub fn fromZoirAlloc(T: type, options: FromZoirAllocOptions) error{ OutOfMemory, ParseZon }!T {322pub fn fromZoirAlloc(T: type, options: FromZoirAllocOptions) error{ OutOfMemory, ParseZon }!T {
455 var out: T = undefined;323 var value: T = undefined;
456 try parseZoirAlloc(324 try parseZoirAlloc(T, &value, .{
457 T,325 .arena = options.arena,
458 &out,326 .ast = options.ast,
459 options.gpa,327 .zoir = options.zoir,
460 options.ast,328 .node = options.node,
461 options.zoir,329 .diag = options.diag,
462 options.node,330 .parser_options = .{
463 options.diag,
464 .{
465 .ignore_unknown_fields = options.ignore_unknown_fields,331 .ignore_unknown_fields = options.ignore_unknown_fields,
466 .ignore_missing_fields = false,332 .ignore_missing_fields = false,
467 .free_on_error = options.free_on_error,
468 .free_on_write = false,
469 },333 },
470 );334 });
471 return out;335 return value;
472}
473
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}336}
491337
492/// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source.338/// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source.
493pub fn updateFromZoirAlloc(339pub fn updateFromZoirAlloc(
494 T: type,340 T: type,
495 options: UpdateFromZoirAllocOptions(T),341 value: *T,
342 options: FromZoirAllocOptions,
496) error{ OutOfMemory, ParseZon }!void {343) error{ OutOfMemory, ParseZon }!void {
497 return parseZoirAlloc(344 return parseZoirAlloc(T, value, .{
498 T,345 .arena = options.arena,
499 options.value,346 .ast = options.ast,
500 options.gpa,347 .zoir = options.zoir,
501 options.ast,348 .node = options.node,
502 options.zoir,349 .diag = options.diag,
503 options.node,350 .parser_options = .{
504 options.diag,
505 .{
506 .ignore_unknown_fields = options.ignore_unknown_fields,351 .ignore_unknown_fields = options.ignore_unknown_fields,
507 .ignore_missing_fields = true,352 .ignore_missing_fields = true,
508 .free_on_error = false,
509 .free_on_write = options.free_on_write,
510 },353 },
511 );354 });
512}355}
513356
514fn parseZoirAlloc(357const ParseZoirAllocOptions = struct {
515 T: type,358 arena: Allocator,
516 out: *T,359 ast: *const Ast,
517 gpa: Allocator,360 zoir: *const Zoir,
518 ast: Ast,
519 zoir: Zoir,
520 node: Zoir.Node.Index,361 node: Zoir.Node.Index,
521 diag: ?*Diagnostics,362 diag: ?*Diagnostics,
522 options: Parser.Options,363 parser_options: Parser.Options,
364};
365
366fn parseZoirAlloc(
367 T: type,
368 value: *T,
369 options: ParseZoirAllocOptions,
523) error{ OutOfMemory, ParseZon }!void {370) error{ OutOfMemory, ParseZon }!void {
524 comptime assert(canParseType(T));371 comptime assert(canParseType(T));
525372
526 if (diag) |s| {373 if (options.zoir.hasCompileErrors()) {
527 s.assertEmpty();374 if (options.diag) |s| {
528 s.ast = ast;375 for (options.zoir.compile_errors) |e| {
529 s.zoir = zoir;376 var notes: std.ArrayList(Error.Note) = .empty;
530 }377 for (e.getNotes(options.zoir)) |note| {
531378 try notes.append(s.arena, .init(options.ast, .{
532 if (zoir.hasCompileErrors()) {379 .msg = try s.arena.dupe(u8, note.msg.get(options.zoir)),
380 .token = note.token,
381 .node_or_offset = note.node_or_offset,
382 }));
383 }
384 try s.compile_errors.append(s.arena, .init(options.ast, .{
385 .msg = try s.arena.dupe(u8, e.msg.get(options.zoir)),
386 .token = e.token,
387 .node_or_offset = e.node_or_offset,
388 .notes = try notes.toOwnedSlice(s.arena),
389 }));
390 }
391 }
533 return error.ParseZon;392 return error.ParseZon;
534 }393 }
535394
536 var parser: Parser = .{395 var parser: Parser = .{
537 .gpa = gpa,396 .arena = options.arena,
538 .ast = ast,397 .ast = options.ast,
539 .zoir = zoir,398 .zoir = options.zoir,
540 .options = options,399 .options = options.parser_options,
541 .diag = diag,400 .diag = options.diag,
542 };401 };
543402
544 try parser.parseExprInto(node, out);403 try parser.parseExprInto(options.node, value);
545}
546
547/// Frees ZON values.
548///
549/// Provided for convenience, you may also free these values on your own using the same allocator
550/// passed into the parser.
551///
552/// Asserts at comptime that sufficient information is available via the type system to free this
553/// value. Untagged unions, for example, will fail this assert.
554pub fn free(gpa: Allocator, value: anytype) void {
555 const Value = @TypeOf(value);
556
557 _ = valid_types;
558 switch (@typeInfo(Value)) {
559 .bool, .int, .float, .@"enum" => {},
560 .pointer => |pointer| {
561 switch (pointer.size) {
562 .one => {
563 free(gpa, value.*);
564 gpa.destroy(value);
565 },
566 .slice => {
567 for (value) |item| {
568 free(gpa, item);
569 }
570 gpa.free(value);
571 },
572 .many, .c => comptime unreachable,
573 }
574 },
575 .array => {
576 freeArray(gpa, @TypeOf(value), &value);
577 },
578 .vector => |vector| {
579 const array: [vector.len]vector.child = value;
580 freeArray(gpa, @TypeOf(array), &array);
581 },
582 .@"struct" => |@"struct"| inline for (@"struct".field_names) |field_name| {
583 free(gpa, @field(value, field_name));
584 },
585 .@"union" => |@"union"| if (@"union".tag_type == null) {
586 if (comptime requiresAllocator(Value)) unreachable;
587 } else switch (value) {
588 inline else => |_, tag| {
589 free(gpa, @field(value, @tagName(tag)));
590 },
591 },
592 .optional => if (value) |some| {
593 free(gpa, some);
594 },
595 .void => {},
596 else => comptime unreachable,
597 }
598}
599
600fn freeArray(gpa: Allocator, comptime A: type, array: *const A) void {
601 for (array) |elem| free(gpa, elem);
602}404}
603405
604fn requiresAllocator(T: type) bool {406fn requiresAllocator(T: type) bool {
...@@ -623,17 +425,15 @@ fn requiresAllocator(T: type) bool {...@@ -623,17 +425,15 @@ fn requiresAllocator(T: type) bool {
623}425}
624426
625const Parser = struct {427const Parser = struct {
626 gpa: Allocator,428 arena: Allocator,
627 ast: Ast,429 ast: *const Ast,
628 zoir: Zoir,430 zoir: *const Zoir,
629 diag: ?*Diagnostics,431 diag: ?*Diagnostics,
630 options: Parser.Options,432 options: Parser.Options,
631 pointer_depth: usize = 0,433 pointer_depth: usize = 0,
632434
633 pub const Options = struct {435 pub const Options = struct {
634 ignore_unknown_fields: bool,436 ignore_unknown_fields: bool,
635 free_on_error: bool,
636 free_on_write: bool,
637 ignore_missing_fields: bool,437 ignore_missing_fields: bool,
638 };438 };
639439
...@@ -654,37 +454,36 @@ const Parser = struct {...@@ -654,37 +454,36 @@ const Parser = struct {
654 out: anytype,454 out: anytype,
655 ) ParseExprInnerError!void {455 ) ParseExprInnerError!void {
656 if (@TypeOf(out.*) == Zoir.Node.Index) {456 if (@TypeOf(out.*) == Zoir.Node.Index) {
657 self.write(out, node);457 out.* = node;
658 return;458 return;
659 }459 }
660460
661 switch (@typeInfo(@TypeOf(out.*))) {461 switch (@typeInfo(@TypeOf(out.*))) {
662 .optional => |optional| if (node.get(self.zoir) == .null) {462 .optional => |optional| if (node.get(self.zoir) == .null) {
663 self.write(out, null);463 out.* = null;
664 } else {464 } else {
665 var new: optional.child = undefined;465 var new: optional.child = undefined;
666 try self.parseExprInnerInto(node, &new);466 try self.parseExprInnerInto(node, &new);
667 self.write(out, new);467 out.* = new;
668 },468 },
669 .bool => self.write(out, try self.parseBool(node)),469 .bool => out.* = try self.parseBool(node),
670 .int => self.write(out, try self.parseInt(@TypeOf(out.*), node)),470 .int => out.* = try self.parseInt(@TypeOf(out.*), node),
671 .float => self.write(out, try self.parseFloat(@TypeOf(out.*), node)),471 .float => out.* = try self.parseFloat(@TypeOf(out.*), node),
672 .@"enum" => self.write(out, try self.parseEnumLiteral(@TypeOf(out.*), node)),472 .@"enum" => out.* = try self.parseEnumLiteral(@TypeOf(out.*), node),
673 .pointer => |pointer| switch (pointer.size) {473 .pointer => |pointer| switch (pointer.size) {
674 .one => {474 .one => {
675 const slice = try self.gpa.alignedAlloc(475 const slice = try self.arena.alignedAlloc(
676 pointer.child,476 pointer.child,
677 if (pointer.attrs.@"align") |a| .fromByteUnits(a) else null,477 if (pointer.attrs.@"align") |a| .fromByteUnits(a) else null,
678 1,478 1,
679 );479 );
680 errdefer self.gpa.free(slice);
681 const new = &slice[0];480 const new = &slice[0];
682 {481 {
683 self.pointer_depth += 1;482 self.pointer_depth += 1;
684 defer self.pointer_depth -= 1;483 defer self.pointer_depth -= 1;
685 try self.parseExprInnerInto(node, new);484 try self.parseExprInnerInto(node, new);
686 }485 }
687 self.write(out, new);486 out.* = new;
688 },487 },
689 .slice => {488 .slice => {
690 const new = b: {489 const new = b: {
...@@ -693,7 +492,7 @@ const Parser = struct {...@@ -693,7 +492,7 @@ const Parser = struct {
693 const new = try self.parseSlicePointer(@TypeOf(out.*), node);492 const new = try self.parseSlicePointer(@TypeOf(out.*), node);
694 break :b new;493 break :b new;
695 };494 };
696 self.write(out, new);495 out.* = new;
697 },496 },
698 else => comptime unreachable,497 else => comptime unreachable,
699 },498 },
...@@ -867,7 +666,7 @@ const Parser = struct {...@@ -867,7 +666,7 @@ const Parser = struct {
867 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);666 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);
868 if (pointer.sentinel() != null) size_hint += 1;667 if (pointer.sentinel() != null) size_hint += 1;
869668
870 var aw: std.Io.Writer.Allocating = .init(self.gpa);669 var aw: std.Io.Writer.Allocating = .init(self.arena);
871 try aw.ensureUnusedCapacity(size_hint);670 try aw.ensureUnusedCapacity(size_hint);
872 defer aw.deinit();671 defer aw.deinit();
873 const result = ZonGen.parseStrLit(self.ast, ast_node, &aw.writer) catch return error.OutOfMemory;672 const result = ZonGen.parseStrLit(self.ast, ast_node, &aw.writer) catch return error.OutOfMemory;
...@@ -906,21 +705,15 @@ const Parser = struct {...@@ -906,21 +705,15 @@ const Parser = struct {
906 }705 }
907706
908 // Allocate the slice707 // Allocate the slice
909 const slice = try self.gpa.allocWithOptions(708 const slice = try self.arena.allocWithOptions(
910 pointer.child,709 pointer.child,
911 nodes.len,710 nodes.len,
912 .fromByteUnitsOptional(pointer.attrs.@"align"),711 .fromByteUnitsOptional(pointer.attrs.@"align"),
913 pointer.sentinel(),712 pointer.sentinel(),
914 );713 );
915 errdefer self.gpa.free(slice);
916714
917 // Parse the elements and return the slice715 // Parse the elements and return the slice
918 for (slice, 0..) |*elem, i| {716 for (slice, 0..) |*elem, i| {
919 errdefer if (self.options.free_on_error) {
920 for (slice[0..i]) |item| {
921 free(self.gpa, item);
922 }
923 };
924 try self.parseExprInto(nodes.at(@intCast(i)), elem);717 try self.parseExprInto(nodes.at(@intCast(i)), elem);
925 }718 }
926719
...@@ -953,13 +746,6 @@ const Parser = struct {...@@ -953,13 +746,6 @@ const Parser = struct {
953746
954 // Parse the elements and return the array747 // Parse the elements and return the array
955 inline for (out, 0..) |*elem, i| {748 inline for (out, 0..) |*elem, i| {
956 // If we fail to parse this field, free all fields before it
957 errdefer if (self.options.free_on_error) {
958 for (out[0..i]) |item| {
959 free(self.gpa, item);
960 }
961 };
962
963 try self.parseExprInto(nodes.at(@intCast(i)), elem);749 try self.parseExprInto(nodes.at(@intCast(i)), elem);
964 }750 }
965751
...@@ -972,7 +758,7 @@ const Parser = struct {...@@ -972,7 +758,7 @@ const Parser = struct {
972 const vector = @typeInfo(@TypeOf(out.*)).vector;758 const vector = @typeInfo(@TypeOf(out.*)).vector;
973 var array: [vector.len]vector.child = undefined;759 var array: [vector.len]vector.child = undefined;
974 try self.parseArrayInto(node, &array);760 try self.parseArrayInto(node, &array);
975 self.write(out, array);761 out.* = array;
976 }762 }
977763
978 fn parseStructInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void {764 fn parseStructInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void {
...@@ -998,22 +784,6 @@ const Parser = struct {...@@ -998,22 +784,6 @@ const Parser = struct {
998784
999 // Parse the struct785 // Parse the struct
1000 var field_found: [info.field_names.len]bool = @splat(false);786 var field_found: [info.field_names.len]bool = @splat(false);
1001
1002 // If we fail partway through, free all already initialized fields
1003 var initialized: usize = 0;
1004 errdefer if (self.options.free_on_error and info.field_names.len > 0) {
1005 for (fields.names[0..initialized]) |name_runtime| {
1006 switch (field_indices.get(name_runtime.get(self.zoir)) orelse continue) {
1007 inline 0...(info.field_names.len - 1) => |name_index| {
1008 const name = info.field_names[name_index];
1009 free(self.gpa, @field(out, name));
1010 },
1011 else => unreachable, // Can't be out of bounds
1012 }
1013 }
1014 };
1015
1016 // Fill in the fields we found
1017 for (0..fields.names.len) |i| {787 for (0..fields.names.len) |i| {
1018 const name = fields.names[i].get(self.zoir);788 const name = fields.names[i].get(self.zoir);
1019 const field_index = field_indices.get(name) orelse {789 const field_index = field_indices.get(name) orelse {
...@@ -1040,8 +810,6 @@ const Parser = struct {...@@ -1040,8 +810,6 @@ const Parser = struct {
1040 },810 },
1041 else => unreachable, // Can't be out of bounds811 else => unreachable, // Can't be out of bounds
1042 }812 }
1043
1044 initialized += 1;
1045 }813 }
1046814
1047 // Fill in any missing default fields815 // Fill in any missing default fields
...@@ -1089,14 +857,6 @@ const Parser = struct {...@@ -1089,14 +857,6 @@ const Parser = struct {
1089 return self.failNodeFmt(node, "missing tuple field with index {}", .{i});857 return self.failNodeFmt(node, "missing tuple field with index {}", .{i});
1090 }858 }
1091 } else {859 } else {
1092 // If we fail to parse this field, free all fields before it
1093 errdefer if (self.options.free_on_error) {
1094 inline for (0..i) |j| {
1095 if (j >= i) break;
1096 free(self.gpa, out[j]);
1097 }
1098 };
1099
1100 if (info.field_attrs[i].@"comptime") {860 if (info.field_attrs[i].@"comptime") {
1101 return self.failComptimeField(node, i);861 return self.failComptimeField(node, i);
1102 } else {862 } else {
...@@ -1144,7 +904,7 @@ const Parser = struct {...@@ -1144,7 +904,7 @@ const Parser = struct {
1144 return self.failNode(node, "expected union");904 return self.failNode(node, "expected union");
1145905
1146 // Instantiate the union906 // Instantiate the union
1147 self.write(out, @unionInit(@TypeOf(out.*), @"union".field_names[i], {}));907 out.* = @unionInit(@TypeOf(out.*), @"union".field_names[i], {});
1148 },908 },
1149 else => unreachable, // Can't be out of bounds909 else => unreachable, // Can't be out of bounds
1150 }910 }
...@@ -1166,7 +926,7 @@ const Parser = struct {...@@ -1166,7 +926,7 @@ const Parser = struct {
1166 if (@"union".field_types[i] == void) {926 if (@"union".field_types[i] == void) {
1167 return self.failNode(field_val, "expected type 'void'");927 return self.failNode(field_val, "expected type 'void'");
1168 } else {928 } else {
1169 self.write(out, @unionInit(@TypeOf(out.*), @"union".field_names[i], undefined));929 out.* = @unionInit(@TypeOf(out.*), @"union".field_names[i], undefined);
1170 try self.parseExprInto(field_val, &@field(out.*, @"union".field_names[i]));930 try self.parseExprInto(field_val, &@field(out.*, @"union".field_names[i]));
1171 }931 }
1172 },932 },
...@@ -1185,7 +945,7 @@ const Parser = struct {...@@ -1185,7 +945,7 @@ const Parser = struct {
1185 args: anytype,945 args: anytype,
1186 ) error{ OutOfMemory, ParseZon } {946 ) error{ OutOfMemory, ParseZon } {
1187 @branchHint(.cold);947 @branchHint(.cold);
1188 return self.failTokenFmtNote(token, offset, fmt, args, null);948 return self.failTokenFmtNote(token, offset, fmt, args, &.{});
1189 }949 }
1190950
1191 fn failTokenFmtNote(951 fn failTokenFmtNote(
...@@ -1194,20 +954,16 @@ const Parser = struct {...@@ -1194,20 +954,16 @@ const Parser = struct {
1194 offset: u32,954 offset: u32,
1195 comptime fmt: []const u8,955 comptime fmt: []const u8,
1196 args: anytype,956 args: anytype,
1197 note: ?Error.TypeCheckFailure.Note,957 notes: []Error.Note,
1198 ) error{ OutOfMemory, ParseZon } {958 ) error{ OutOfMemory, ParseZon } {
1199 @branchHint(.cold);959 @branchHint(.cold);
1200 comptime assert(args.len > 0);960 comptime assert(args.len > 0);
1201 if (self.diag) |s| s.type_check = .{961 if (self.diag) |s| try s.compile_errors.append(s.arena, .init(self.ast, .{
1202 .token = token,962 .token = .fromToken(token),
1203 .offset = offset,963 .node_or_offset = offset,
1204 .message = std.fmt.allocPrint(self.gpa, fmt, args) catch |err| {964 .msg = try std.fmt.allocPrint(s.arena, fmt, args),
1205 if (note) |n| n.deinit(self.gpa);965 .notes = notes,
1206 return err;966 }));
1207 },
1208 .owned = true,
1209 .note = note,
1210 };
1211 return error.ParseZon;967 return error.ParseZon;
1212 }968 }
1213969
...@@ -1224,27 +980,26 @@ const Parser = struct {...@@ -1224,27 +980,26 @@ const Parser = struct {
1224980
1225 fn failToken(981 fn failToken(
1226 self: @This(),982 self: @This(),
1227 failure: Error.TypeCheckFailure,983 failure: Error,
1228 ) error{ParseZon} {984 ) error{ OutOfMemory, ParseZon } {
1229 @branchHint(.cold);985 @branchHint(.cold);
1230 if (self.diag) |s| s.type_check = failure;986 if (self.diag) |s| try s.compile_errors.append(s.arena, failure);
1231 return error.ParseZon;987 return error.ParseZon;
1232 }988 }
1233989
1234 fn failNode(990 fn failNode(
1235 self: @This(),991 self: @This(),
1236 node: Zoir.Node.Index,992 node: Zoir.Node.Index,
1237 message: []const u8,993 msg: []const u8,
1238 ) error{ParseZon} {994 ) error{ OutOfMemory, ParseZon } {
1239 @branchHint(.cold);995 @branchHint(.cold);
1240 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));996 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));
1241 return self.failToken(.{997 return self.failToken(.init(self.ast, .{
1242 .token = token,998 .token = .fromToken(token),
1243 .offset = 0,999 .node_or_offset = 0,
1244 .message = message,1000 .msg = msg,
1245 .owned = false,1001 .notes = &.{},
1246 .note = null,1002 }));
1247 });
1248 }1003 }
12491004
1250 fn failCannotRepresent(1005 fn failCannotRepresent(
...@@ -1265,8 +1020,7 @@ const Parser = struct {...@@ -1265,8 +1020,7 @@ const Parser = struct {
1265 name: []const u8,1020 name: []const u8,
1266 ) error{ OutOfMemory, ParseZon } {1021 ) error{ OutOfMemory, ParseZon } {
1267 @branchHint(.cold);1022 @branchHint(.cold);
1268 if (self.diag == null) return error.ParseZon;1023 const diag = self.diag orelse return error.ParseZon;
1269 const gpa = self.gpa;
1270 const token = if (field) |f| b: {1024 const token = if (field) |f| b: {
1271 var buf: [2]Ast.Node.Index = undefined;1025 var buf: [2]Ast.Node.Index = undefined;
1272 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;1026 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;
...@@ -1275,38 +1029,35 @@ const Parser = struct {...@@ -1275,38 +1029,35 @@ const Parser = struct {
1275 } else self.ast.nodeMainToken(node.getAstNode(self.zoir));1029 } else self.ast.nodeMainToken(node.getAstNode(self.zoir));
1276 switch (@typeInfo(T)) {1030 switch (@typeInfo(T)) {
1277 inline .@"struct", .@"union", .@"enum" => |info| {1031 inline .@"struct", .@"union", .@"enum" => |info| {
1278 const note: Error.TypeCheckFailure.Note = if (info.field_names.len == 0) b: {1032 var notes: std.ArrayList(Error.Note) = .empty;
1279 break :b .{1033 if (info.field_names.len == 0) {
1280 .token = token,1034 try notes.append(diag.arena, .init(self.ast, .{
1281 .offset = 0,1035 .token = .fromToken(token),
1036 .node_or_offset = 0,
1282 .msg = "none expected",1037 .msg = "none expected",
1283 .owned = false,1038 }));
1284 };1039 } else {
1285 } else b: {1040 var aw: std.Io.Writer.Allocating = .init(diag.arena);
1286 const msg = "supported: ";1041 aw.writer.writeAll("supported: ") catch return error.OutOfMemory;
1287 var buf: std.ArrayList(u8) = try .initCapacity(gpa, 64);
1288 defer buf.deinit(gpa);
1289 try buf.appendSlice(gpa, msg);
1290 inline for (info.field_names, 0..) |field_name, i| {1042 inline for (info.field_names, 0..) |field_name, i| {
1291 if (i != 0) try buf.appendSlice(gpa, ", ");1043 if (i != 0) aw.writer.writeAll(", ") catch return error.OutOfMemory;
1292 try buf.print(gpa, "'{f}'", .{std.zig.fmtIdFlags(field_name, .{1044 aw.writer.print("'{f}'", .{std.zig.fmtIdFlags(field_name, .{
1293 .allow_primitive = true,1045 .allow_primitive = true,
1294 .allow_underscore = true,1046 .allow_underscore = true,
1295 })});1047 })}) catch return error.OutOfMemory;
1296 }1048 }
1297 break :b .{1049 try notes.append(diag.arena, .init(self.ast, .{
1298 .token = token,1050 .token = .fromToken(token),
1299 .offset = 0,1051 .node_or_offset = 0,
1300 .msg = try buf.toOwnedSlice(gpa),1052 .msg = try aw.toOwnedSlice(),
1301 .owned = true,1053 }));
1302 };1054 }
1303 };
1304 return self.failTokenFmtNote(1055 return self.failTokenFmtNote(
1305 token,1056 token,
1306 0,1057 0,
1307 "unexpected {s} '{s}'",1058 "unexpected {s} '{s}'",
1308 .{ item_kind, name },1059 .{ item_kind, name },
1309 note,1060 try notes.toOwnedSlice(diag.arena),
1310 );1061 );
1311 },1062 },
1312 else => comptime unreachable,1063 else => comptime unreachable,
...@@ -1333,23 +1084,12 @@ const Parser = struct {...@@ -1333,23 +1084,12 @@ const Parser = struct {
1333 const value_node = array_init.ast.elements[field];1084 const value_node = array_init.ast.elements[field];
1334 break :b self.ast.firstToken(value_node);1085 break :b self.ast.firstToken(value_node);
1335 };1086 };
1336 return self.failToken(.{1087 return self.failToken(.init(self.ast, .{
1337 .token = token,1088 .token = .fromToken(token),
1338 .offset = 0,1089 .node_or_offset = 0,
1339 .message = "cannot initialize comptime field",1090 .msg = "cannot initialize comptime field",
1340 .owned = false,1091 .notes = &.{},
1341 .note = null,1092 }));
1342 });
1343 }
1344
1345 /// Write to out, freeing the old value first if necessary.
1346 fn write(self: *@This(), out: anytype, new: @TypeOf(out.*)) void {
1347 if (@typeInfo(@TypeOf(out)) == .pointer) {
1348 if (self.options.free_on_write and self.pointer_depth == 0) {
1349 free(self.gpa, out.*);
1350 }
1351 }
1352 out.* = new;
1353 }1093 }
1354};1094};
13551095
...@@ -1511,17 +1251,26 @@ test "std.zon requiresAllocator" {...@@ -1511,17 +1251,26 @@ test "std.zon requiresAllocator" {
15111251
1512test "std.zon ast errors" {1252test "std.zon ast errors" {
1513 const gpa = std.testing.allocator;1253 const gpa = std.testing.allocator;
1514 var diag: Diagnostics = .{};1254 var arena_allocator: ArenaAllocator = .init(gpa);
1515 defer diag.deinit(gpa);1255 defer arena_allocator.deinit();
1256 const arena = arena_allocator.allocator();
1257 var diag: Diagnostics = .init(arena);
1516 try std.testing.expectError(1258 try std.testing.expectError(
1517 error.ParseZon,1259 error.ParseZon,
1518 fromSlice(struct {}, .{ .gpa = gpa, .source = ".{.x = 1 .y = 2}", .diag = &diag }),1260 fromSlice(struct {}, .{
1261 .gpa = gpa,
1262 .source = ".{.x = 1 .y = 2}",
1263 .diag = &diag,
1264 }),
1519 );1265 );
1520 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{diag});1266 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{diag});
1521}1267}
15221268
1523test "std.zon comments" {1269test "std.zon comments" {
1524 const gpa = std.testing.allocator;1270 const gpa = std.testing.allocator;
1271 var arena_allocator: ArenaAllocator = .init(gpa);
1272 defer arena_allocator.deinit();
1273 const arena = arena_allocator.allocator();
15251274
1526 try std.testing.expectEqual(@as(u8, 10), fromSlice(u8, .{1275 try std.testing.expectEqual(@as(u8, 10), fromSlice(u8, .{
1527 .gpa = gpa,1276 .gpa = gpa,
...@@ -1534,8 +1283,7 @@ test "std.zon comments" {...@@ -1534,8 +1283,7 @@ test "std.zon comments" {
1534 }));1283 }));
15351284
1536 {1285 {
1537 var diag: Diagnostics = .{};1286 var diag: Diagnostics = .init(arena);
1538 defer diag.deinit(gpa);
1539 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{1287 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
1540 .gpa = gpa,1288 .gpa = gpa,
1541 .source =1289 .source =
...@@ -1555,10 +1303,13 @@ test "std.zon comments" {...@@ -1555,10 +1303,13 @@ test "std.zon comments" {
15551303
1556test "std.zon failure/oom formatting" {1304test "std.zon failure/oom formatting" {
1557 const gpa = std.testing.allocator;1305 const gpa = std.testing.allocator;
1558 var diag: Diagnostics = .{};1306 var arena_allocator: ArenaAllocator = .init(gpa);
1559 defer diag.deinit(gpa);1307 defer arena_allocator.deinit();
1308 const arena = arena_allocator.allocator();
1309 var diag: Diagnostics = .init(arena);
1560 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc([]const u8, .{1310 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc([]const u8, .{
1561 .gpa = .failing,1311 .gpa = .failing,
1312 .arena = arena,
1562 .source = "\"foo\"",1313 .source = "\"foo\"",
1563 .diag = &diag,1314 .diag = &diag,
1564 }));1315 }));
...@@ -1566,10 +1317,11 @@ test "std.zon failure/oom formatting" {...@@ -1566,10 +1317,11 @@ test "std.zon failure/oom formatting" {
1566}1317}
15671318
1568test "std.zon fromSliceAlloc syntax error" {1319test "std.zon fromSliceAlloc syntax error" {
1320 const gpa = std.testing.allocator;
1569 try std.testing.expectError(1321 try std.testing.expectError(
1570 error.ParseZon,1322 error.ParseZon,
1571 fromSlice(u8, .{1323 fromSlice(u8, .{
1572 .gpa = std.testing.allocator,1324 .gpa = gpa,
1573 .source = ".{",1325 .source = ".{",
1574 .diag = null,1326 .diag = null,
1575 }),1327 }),
...@@ -1578,6 +1330,9 @@ test "std.zon fromSliceAlloc syntax error" {...@@ -1578,6 +1330,9 @@ test "std.zon fromSliceAlloc syntax error" {
15781330
1579test "std.zon optional" {1331test "std.zon optional" {
1580 const gpa = std.testing.allocator;1332 const gpa = std.testing.allocator;
1333 var arena_allocator: ArenaAllocator = .init(gpa);
1334 defer arena_allocator.deinit();
1335 const arena = arena_allocator.allocator();
15811336
1582 // Basic usage1337 // Basic usage
1583 {1338 {
...@@ -1599,22 +1354,26 @@ test "std.zon optional" {...@@ -1599,22 +1354,26 @@ test "std.zon optional" {
1599 {1354 {
1600 const none = try fromSliceAlloc(?[]const u8, .{1355 const none = try fromSliceAlloc(?[]const u8, .{
1601 .gpa = gpa,1356 .gpa = gpa,
1357 .arena = arena,
1602 .source = "null",1358 .source = "null",
1603 .diag = null,1359 .diag = null,
1604 });1360 });
1605 try std.testing.expect(none == null);1361 try std.testing.expect(none == null);
1606 const some = try fromSliceAlloc(?[]const u8, .{1362 const some = try fromSliceAlloc(?[]const u8, .{
1607 .gpa = gpa,1363 .gpa = gpa,
1364 .arena = arena,
1608 .source = "\"foo\"",1365 .source = "\"foo\"",
1609 .diag = null,1366 .diag = null,
1610 });1367 });
1611 defer free(gpa, some);
1612 try std.testing.expectEqualStrings("foo", some.?);1368 try std.testing.expectEqualStrings("foo", some.?);
1613 }1369 }
1614}1370}
16151371
1616test "std.zon unions" {1372test "std.zon unions" {
1617 const gpa = std.testing.allocator;1373 const gpa = std.testing.allocator;
1374 var arena_allocator: ArenaAllocator = .init(gpa);
1375 defer arena_allocator.deinit();
1376 const arena = arena_allocator.allocator();
16181377
1619 // Unions1378 // Unions
1620 {1379 {
...@@ -1666,6 +1425,7 @@ test "std.zon unions" {...@@ -1666,6 +1425,7 @@ test "std.zon unions" {
16661425
1667 const noalloc = try fromSliceAlloc(Union, .{1426 const noalloc = try fromSliceAlloc(Union, .{
1668 .gpa = gpa,1427 .gpa = gpa,
1428 .arena = arena,
1669 .source = ".{.baz = false}",1429 .source = ".{.baz = false}",
1670 .diag = null,1430 .diag = null,
1671 });1431 });
...@@ -1673,21 +1433,25 @@ test "std.zon unions" {...@@ -1673,21 +1433,25 @@ test "std.zon unions" {
16731433
1674 const alloc = try fromSliceAlloc(Union, .{1434 const alloc = try fromSliceAlloc(Union, .{
1675 .gpa = gpa,1435 .gpa = gpa,
1436 .arena = arena,
1676 .source = ".{.bar = \"qux\"}",1437 .source = ".{.bar = \"qux\"}",
1677 .diag = null,1438 .diag = null,
1678 });1439 });
1679 defer free(gpa, alloc);
1680 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);1440 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);
1681 }1441 }
16821442
1683 // Unknown field1443 // Unknown field
1684 {1444 {
1685 const Union = union { x: f32, y: f32 };1445 const Union = union { x: f32, y: f32 };
1686 var diag: Diagnostics = .{};1446 var diag: Diagnostics = .init(arena);
1687 defer diag.deinit(gpa);
1688 try std.testing.expectError(1447 try std.testing.expectError(
1689 error.ParseZon,1448 error.ParseZon,
1690 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{.z=2.5}", .diag = &diag }),1449 fromSliceAlloc(Union, .{
1450 .gpa = gpa,
1451 .arena = arena,
1452 .source = ".{.z=2.5}",
1453 .diag = &diag,
1454 }),
1691 );1455 );
1692 try std.testing.expectFmt(1456 try std.testing.expectFmt(
1693 \\1:4: error: unexpected field 'z'1457 \\1:4: error: unexpected field 'z'
...@@ -1702,11 +1466,15 @@ test "std.zon unions" {...@@ -1702,11 +1466,15 @@ test "std.zon unions" {
1702 // Explicit void field1466 // Explicit void field
1703 {1467 {
1704 const Union = union(enum) { x: void };1468 const Union = union(enum) { x: void };
1705 var diag: Diagnostics = .{};1469 var diag: Diagnostics = .init(arena);
1706 defer diag.deinit(gpa);
1707 try std.testing.expectError(1470 try std.testing.expectError(
1708 error.ParseZon,1471 error.ParseZon,
1709 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{.x=1}", .diag = &diag }),1472 fromSliceAlloc(Union, .{
1473 .gpa = gpa,
1474 .arena = arena,
1475 .source = ".{.x=1}",
1476 .diag = &diag,
1477 }),
1710 );1478 );
1711 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});1479 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
1712 }1480 }
...@@ -1714,12 +1482,12 @@ test "std.zon unions" {...@@ -1714,12 +1482,12 @@ test "std.zon unions" {
1714 // Extra field1482 // Extra field
1715 {1483 {
1716 const Union = union { x: f32, y: bool };1484 const Union = union { x: f32, y: bool };
1717 var diag: Diagnostics = .{};1485 var diag: Diagnostics = .init(arena);
1718 defer diag.deinit(gpa);
1719 try std.testing.expectError(1486 try std.testing.expectError(
1720 error.ParseZon,1487 error.ParseZon,
1721 fromSliceAlloc(Union, .{1488 fromSliceAlloc(Union, .{
1722 .gpa = gpa,1489 .gpa = gpa,
1490 .arena = arena,
1723 .source = ".{.x = 1.5, .y = true}",1491 .source = ".{.x = 1.5, .y = true}",
1724 .diag = &diag,1492 .diag = &diag,
1725 }),1493 }),
...@@ -1730,11 +1498,15 @@ test "std.zon unions" {...@@ -1730,11 +1498,15 @@ test "std.zon unions" {
1730 // No fields1498 // No fields
1731 {1499 {
1732 const Union = union { x: f32, y: bool };1500 const Union = union { x: f32, y: bool };
1733 var diag: Diagnostics = .{};1501 var diag: Diagnostics = .init(arena);
1734 defer diag.deinit(gpa);
1735 try std.testing.expectError(1502 try std.testing.expectError(
1736 error.ParseZon,1503 error.ParseZon,
1737 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{}", .diag = &diag }),1504 fromSliceAlloc(Union, .{
1505 .gpa = gpa,
1506 .arena = arena,
1507 .source = ".{}",
1508 .diag = &diag,
1509 }),
1738 );1510 );
1739 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});1511 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
1740 }1512 }
...@@ -1742,10 +1514,10 @@ test "std.zon unions" {...@@ -1742,10 +1514,10 @@ test "std.zon unions" {
1742 // Enum literals cannot coerce into untagged unions1514 // Enum literals cannot coerce into untagged unions
1743 {1515 {
1744 const Union = union { x: void };1516 const Union = union { x: void };
1745 var diag: Diagnostics = .{};1517 var diag: Diagnostics = .init(arena);
1746 defer diag.deinit(gpa);
1747 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{1518 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1748 .gpa = gpa,1519 .gpa = gpa,
1520 .arena = arena,
1749 .source = ".x",1521 .source = ".x",
1750 .diag = &diag,1522 .diag = &diag,
1751 }));1523 }));
...@@ -1755,10 +1527,10 @@ test "std.zon unions" {...@@ -1755,10 +1527,10 @@ test "std.zon unions" {
1755 // Unknown field for enum literal coercion1527 // Unknown field for enum literal coercion
1756 {1528 {
1757 const Union = union(enum) { x: void };1529 const Union = union(enum) { x: void };
1758 var diag: Diagnostics = .{};1530 var diag: Diagnostics = .init(arena);
1759 defer diag.deinit(gpa);
1760 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{1531 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1761 .gpa = gpa,1532 .gpa = gpa,
1533 .arena = arena,
1762 .source = ".y",1534 .source = ".y",
1763 .diag = &diag,1535 .diag = &diag,
1764 }));1536 }));
...@@ -1775,10 +1547,10 @@ test "std.zon unions" {...@@ -1775,10 +1547,10 @@ test "std.zon unions" {
1775 // Non void field for enum literal coercion1547 // Non void field for enum literal coercion
1776 {1548 {
1777 const Union = union(enum) { x: f32 };1549 const Union = union(enum) { x: f32 };
1778 var diag: Diagnostics = .{};1550 var diag: Diagnostics = .init(arena);
1779 defer diag.deinit(gpa);
1780 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{1551 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1781 .gpa = gpa,1552 .gpa = gpa,
1553 .arena = arena,
1782 .source = ".x",1554 .source = ".x",
1783 .diag = &diag,1555 .diag = &diag,
1784 }));1556 }));
...@@ -1788,6 +1560,9 @@ test "std.zon unions" {...@@ -1788,6 +1560,9 @@ test "std.zon unions" {
17881560
1789test "std.zon structs" {1561test "std.zon structs" {
1790 const gpa = std.testing.allocator;1562 const gpa = std.testing.allocator;
1563 var arena_allocator: ArenaAllocator = .init(gpa);
1564 defer arena_allocator.deinit();
1565 const arena = arena_allocator.allocator();
17911566
1792 // Structs (various sizes tested since they're parsed differently)1567 // Structs (various sizes tested since they're parsed differently)
1793 {1568 {
...@@ -1831,21 +1606,24 @@ test "std.zon structs" {...@@ -1831,21 +1606,24 @@ test "std.zon structs" {
18311606
1832 const parsed = try fromSliceAlloc(Foo, .{1607 const parsed = try fromSliceAlloc(Foo, .{
1833 .gpa = gpa,1608 .gpa = gpa,
1609 .arena = arena,
1834 .source = ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",1610 .source = ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
1835 .diag = null,1611 .diag = null,
1836 });1612 });
1837 defer free(gpa, parsed);
1838 try std.testing.expectEqualDeep(Foo{ .bar = "qux", .baz = &.{ "a", "b" } }, parsed);1613 try std.testing.expectEqualDeep(Foo{ .bar = "qux", .baz = &.{ "a", "b" } }, parsed);
1839 }1614 }
18401615
1841 // Unknown field1616 // Unknown field
1842 {1617 {
1843 const Vec2 = struct { x: f32, y: f32 };1618 const Vec2 = struct { x: f32, y: f32 };
1844 var diag: Diagnostics = .{};1619 var diag: Diagnostics = .init(arena);
1845 defer diag.deinit(gpa);
1846 try std.testing.expectError(1620 try std.testing.expectError(
1847 error.ParseZon,1621 error.ParseZon,
1848 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .z=2.5}", .diag = &diag }),1622 fromSlice(Vec2, .{
1623 .gpa = gpa,
1624 .source = ".{.x=1.5, .z=2.5}",
1625 .diag = &diag,
1626 }),
1849 );1627 );
1850 try std.testing.expectFmt(1628 try std.testing.expectFmt(
1851 \\1:12: error: unexpected field 'z'1629 \\1:12: error: unexpected field 'z'
...@@ -1860,11 +1638,14 @@ test "std.zon structs" {...@@ -1860,11 +1638,14 @@ test "std.zon structs" {
1860 // Duplicate field1638 // Duplicate field
1861 {1639 {
1862 const Vec2 = struct { x: f32, y: f32 };1640 const Vec2 = struct { x: f32, y: f32 };
1863 var diag: Diagnostics = .{};1641 var diag: Diagnostics = .init(arena);
1864 defer diag.deinit(gpa);
1865 try std.testing.expectError(1642 try std.testing.expectError(
1866 error.ParseZon,1643 error.ParseZon,
1867 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .x=2.5, .x=3.5}", .diag = &diag }),1644 fromSlice(Vec2, .{
1645 .gpa = gpa,
1646 .source = ".{.x=1.5, .x=2.5, .x=3.5}",
1647 .diag = &diag,
1648 }),
1868 );1649 );
1869 try std.testing.expectFmt(1650 try std.testing.expectFmt(
1870 \\1:4: error: duplicate struct field name1651 \\1:4: error: duplicate struct field name
...@@ -1888,11 +1669,14 @@ test "std.zon structs" {...@@ -1888,11 +1669,14 @@ test "std.zon structs" {
1888 // Unknown field when struct has no fields (regression test)1669 // Unknown field when struct has no fields (regression test)
1889 {1670 {
1890 const Vec2 = struct {};1671 const Vec2 = struct {};
1891 var diag: Diagnostics = .{};1672 var diag: Diagnostics = .init(arena);
1892 defer diag.deinit(gpa);
1893 try std.testing.expectError(1673 try std.testing.expectError(
1894 error.ParseZon,1674 error.ParseZon,
1895 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .z=2.5}", .diag = &diag }),1675 fromSlice(Vec2, .{
1676 .gpa = gpa,
1677 .source = ".{.x=1.5, .z=2.5}",
1678 .diag = &diag,
1679 }),
1896 );1680 );
1897 try std.testing.expectFmt(1681 try std.testing.expectFmt(
1898 \\1:4: error: unexpected field 'x'1682 \\1:4: error: unexpected field 'x'
...@@ -1904,11 +1688,14 @@ test "std.zon structs" {...@@ -1904,11 +1688,14 @@ test "std.zon structs" {
1904 // Missing field1688 // Missing field
1905 {1689 {
1906 const Vec2 = struct { x: f32, y: f32 };1690 const Vec2 = struct { x: f32, y: f32 };
1907 var diag: Diagnostics = .{};1691 var diag: Diagnostics = .init(arena);
1908 defer diag.deinit(gpa);
1909 try std.testing.expectError(1692 try std.testing.expectError(
1910 error.ParseZon,1693 error.ParseZon,
1911 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5}", .diag = &diag }),1694 fromSlice(Vec2, .{
1695 .gpa = gpa,
1696 .source = ".{.x=1.5}",
1697 .diag = &diag,
1698 }),
1912 );1699 );
1913 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{diag});1700 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{diag});
1914 }1701 }
...@@ -1916,22 +1703,29 @@ test "std.zon structs" {...@@ -1916,22 +1703,29 @@ test "std.zon structs" {
1916 // Default field1703 // Default field
1917 {1704 {
1918 const Vec2 = struct { x: f32, y: f32 = 1.5 };1705 const Vec2 = struct { x: f32, y: f32 = 1.5 };
1919 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x = 1.2}", .diag = null });1706 const parsed = try fromSlice(Vec2, .{
1707 .gpa = gpa,
1708 .source = ".{.x = 1.2}",
1709 .diag = null,
1710 });
1920 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);1711 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
1921 }1712 }
19221713
1923 // Comptime field1714 // Comptime field
1924 {1715 {
1925 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };1716 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1926 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x = 1.2}", .diag = null });1717 const parsed = try fromSlice(Vec2, .{
1718 .gpa = gpa,
1719 .source = ".{.x = 1.2}",
1720 .diag = null,
1721 });
1927 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);1722 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
1928 }1723 }
19291724
1930 // Comptime field assignment1725 // Comptime field assignment
1931 {1726 {
1932 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };1727 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1933 var diag: Diagnostics = .{};1728 var diag: Diagnostics = .init(arena);
1934 defer diag.deinit(gpa);
1935 const parsed = fromSlice(Vec2, .{1729 const parsed = fromSlice(Vec2, .{
1936 .gpa = gpa,1730 .gpa = gpa,
1937 .source = ".{.x = 1.2, .y = 1.5}",1731 .source = ".{.x = 1.2, .y = 1.5}",
...@@ -1971,8 +1765,7 @@ test "std.zon structs" {...@@ -1971,8 +1765,7 @@ test "std.zon structs" {
1971 {1765 {
1972 // Structs1766 // Structs
1973 {1767 {
1974 var diag: Diagnostics = .{};1768 var diag: Diagnostics = .init(arena);
1975 defer diag.deinit(gpa);
1976 const parsed = fromSlice(struct {}, .{1769 const parsed = fromSlice(struct {}, .{
1977 .gpa = gpa,1770 .gpa = gpa,
1978 .source = "Empty{}",1771 .source = "Empty{}",
...@@ -1988,8 +1781,7 @@ test "std.zon structs" {...@@ -1988,8 +1781,7 @@ test "std.zon structs" {
19881781
1989 // Arrays1782 // Arrays
1990 {1783 {
1991 var diag: Diagnostics = .{};1784 var diag: Diagnostics = .init(arena);
1992 defer diag.deinit(gpa);
1993 const parsed = fromSlice([3]u8, .{1785 const parsed = fromSlice([3]u8, .{
1994 .gpa = gpa,1786 .gpa = gpa,
1995 .source = "[3]u8{1, 2, 3}",1787 .source = "[3]u8{1, 2, 3}",
...@@ -2005,10 +1797,10 @@ test "std.zon structs" {...@@ -2005,10 +1797,10 @@ test "std.zon structs" {
20051797
2006 // Slices1798 // Slices
2007 {1799 {
2008 var diag: Diagnostics = .{};1800 var diag: Diagnostics = .init(arena);
2009 defer diag.deinit(gpa);
2010 const parsed = fromSliceAlloc([]u8, .{1801 const parsed = fromSliceAlloc([]u8, .{
2011 .gpa = gpa,1802 .gpa = gpa,
1803 .arena = arena,
2012 .source = "[]u8{1, 2, 3}",1804 .source = "[]u8{1, 2, 3}",
2013 .diag = &diag,1805 .diag = &diag,
2014 });1806 });
...@@ -2022,8 +1814,7 @@ test "std.zon structs" {...@@ -2022,8 +1814,7 @@ test "std.zon structs" {
20221814
2023 // Tuples1815 // Tuples
2024 {1816 {
2025 var diag: Diagnostics = .{};1817 var diag: Diagnostics = .init(arena);
2026 defer diag.deinit(gpa);
2027 const parsed = fromSlice(struct { u8, u8, u8 }, .{1818 const parsed = fromSlice(struct { u8, u8, u8 }, .{
2028 .gpa = gpa,1819 .gpa = gpa,
2029 .source = "Tuple{1, 2, 3}",1820 .source = "Tuple{1, 2, 3}",
...@@ -2039,8 +1830,7 @@ test "std.zon structs" {...@@ -2039,8 +1830,7 @@ test "std.zon structs" {
20391830
2040 // Nested1831 // Nested
2041 {1832 {
2042 var diag: Diagnostics = .{};1833 var diag: Diagnostics = .init(arena);
2043 defer diag.deinit(gpa);
2044 const parsed = fromSlice(struct {}, .{1834 const parsed = fromSlice(struct {}, .{
2045 .gpa = gpa,1835 .gpa = gpa,
2046 .source = ".{ .x = Tuple{1, 2, 3} }",1836 .source = ".{ .x = Tuple{1, 2, 3} }",
...@@ -2058,6 +1848,9 @@ test "std.zon structs" {...@@ -2058,6 +1848,9 @@ test "std.zon structs" {
20581848
2059test "std.zon tuples" {1849test "std.zon tuples" {
2060 const gpa = std.testing.allocator;1850 const gpa = std.testing.allocator;
1851 var arena_allocator: ArenaAllocator = .init(gpa);
1852 defer arena_allocator.deinit();
1853 const arena = arena_allocator.allocator();
20611854
2062 // Structs (various sizes tested since they're parsed differently)1855 // Structs (various sizes tested since they're parsed differently)
2063 {1856 {
...@@ -2100,21 +1893,24 @@ test "std.zon tuples" {...@@ -2100,21 +1893,24 @@ test "std.zon tuples" {
2100 const Tuple = struct { []const u8, []const u8 };1893 const Tuple = struct { []const u8, []const u8 };
2101 const parsed = try fromSliceAlloc(Tuple, .{1894 const parsed = try fromSliceAlloc(Tuple, .{
2102 .gpa = gpa,1895 .gpa = gpa,
1896 .arena = arena,
2103 .source = ".{\"hello\", \"world\"}",1897 .source = ".{\"hello\", \"world\"}",
2104 .diag = null,1898 .diag = null,
2105 });1899 });
2106 defer free(gpa, parsed);
2107 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);1900 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);
2108 }1901 }
21091902
2110 // Extra field1903 // Extra field
2111 {1904 {
2112 const Tuple = struct { f32, bool };1905 const Tuple = struct { f32, bool };
2113 var diag: Diagnostics = .{};1906 var diag: Diagnostics = .init(arena);
2114 defer diag.deinit(gpa);
2115 try std.testing.expectError(1907 try std.testing.expectError(
2116 error.ParseZon,1908 error.ParseZon,
2117 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{0.5, true, 123}", .diag = &diag }),1909 fromSlice(Tuple, .{
1910 .gpa = gpa,
1911 .source = ".{0.5, true, 123}",
1912 .diag = &diag,
1913 }),
2118 );1914 );
2119 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{diag});1915 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{diag});
2120 }1916 }
...@@ -2122,11 +1918,14 @@ test "std.zon tuples" {...@@ -2122,11 +1918,14 @@ test "std.zon tuples" {
2122 // Extra field1918 // Extra field
2123 {1919 {
2124 const Tuple = struct { f32, bool };1920 const Tuple = struct { f32, bool };
2125 var diag: Diagnostics = .{};1921 var diag: Diagnostics = .init(arena);
2126 defer diag.deinit(gpa);
2127 try std.testing.expectError(1922 try std.testing.expectError(
2128 error.ParseZon,1923 error.ParseZon,
2129 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{0.5}", .diag = &diag }),1924 fromSlice(Tuple, .{
1925 .gpa = gpa,
1926 .source = ".{0.5}",
1927 .diag = &diag,
1928 }),
2130 );1929 );
2131 try std.testing.expectFmt(1930 try std.testing.expectFmt(
2132 "1:2: error: missing tuple field with index 1\n",1931 "1:2: error: missing tuple field with index 1\n",
...@@ -2138,11 +1937,14 @@ test "std.zon tuples" {...@@ -2138,11 +1937,14 @@ test "std.zon tuples" {
2138 // Tuple with unexpected field names1937 // Tuple with unexpected field names
2139 {1938 {
2140 const Tuple = struct { f32 };1939 const Tuple = struct { f32 };
2141 var diag: Diagnostics = .{};1940 var diag: Diagnostics = .init(arena);
2142 defer diag.deinit(gpa);
2143 try std.testing.expectError(1941 try std.testing.expectError(
2144 error.ParseZon,1942 error.ParseZon,
2145 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{.foo = 10.0}", .diag = &diag }),1943 fromSlice(Tuple, .{
1944 .gpa = gpa,
1945 .source = ".{.foo = 10.0}",
1946 .diag = &diag,
1947 }),
2146 );1948 );
2147 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{diag});1949 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{diag});
2148 }1950 }
...@@ -2150,11 +1952,14 @@ test "std.zon tuples" {...@@ -2150,11 +1952,14 @@ test "std.zon tuples" {
2150 // Struct with missing field names1952 // Struct with missing field names
2151 {1953 {
2152 const Struct = struct { foo: f32 };1954 const Struct = struct { foo: f32 };
2153 var diag: Diagnostics = .{};1955 var diag: Diagnostics = .init(arena);
2154 defer diag.deinit(gpa);
2155 try std.testing.expectError(1956 try std.testing.expectError(
2156 error.ParseZon,1957 error.ParseZon,
2157 fromSlice(Struct, .{ .gpa = gpa, .source = ".{10.0}", .diag = &diag }),1958 fromSlice(Struct, .{
1959 .gpa = gpa,
1960 .source = ".{10.0}",
1961 .diag = &diag,
1962 }),
2158 );1963 );
2159 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{diag});1964 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{diag});
2160 }1965 }
...@@ -2162,16 +1967,23 @@ test "std.zon tuples" {...@@ -2162,16 +1967,23 @@ test "std.zon tuples" {
2162 // Comptime field1967 // Comptime field
2163 {1968 {
2164 const Vec2 = struct { f32, comptime f32 = 1.5 };1969 const Vec2 = struct { f32, comptime f32 = 1.5 };
2165 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{ 1.2 }", .diag = null });1970 const parsed = try fromSlice(Vec2, .{
1971 .gpa = gpa,
1972 .source = ".{ 1.2 }",
1973 .diag = null,
1974 });
2166 try std.testing.expectEqual(Vec2{ 1.2, 1.5 }, parsed);1975 try std.testing.expectEqual(Vec2{ 1.2, 1.5 }, parsed);
2167 }1976 }
21681977
2169 // Comptime field assignment1978 // Comptime field assignment
2170 {1979 {
2171 const Vec2 = struct { f32, comptime f32 = 1.5 };1980 const Vec2 = struct { f32, comptime f32 = 1.5 };
2172 var diag: Diagnostics = .{};1981 var diag: Diagnostics = .init(arena);
2173 defer diag.deinit(gpa);1982 const parsed = fromSlice(Vec2, .{
2174 const parsed = fromSlice(Vec2, .{ .gpa = gpa, .source = ".{ 1.2, 1.5}", .diag = &diag });1983 .gpa = gpa,
1984 .source = ".{ 1.2, 1.5}",
1985 .diag = &diag,
1986 });
2175 try std.testing.expectError(error.ParseZon, parsed);1987 try std.testing.expectError(error.ParseZon, parsed);
2176 try std.testing.expectFmt(1988 try std.testing.expectFmt(
2177 \\1:9: error: cannot initialize comptime field1989 \\1:9: error: cannot initialize comptime field
...@@ -2183,6 +1995,9 @@ test "std.zon tuples" {...@@ -2183,6 +1995,9 @@ test "std.zon tuples" {
2183// Test sizes 0 to 3 since small sizes get parsed differently1995// Test sizes 0 to 3 since small sizes get parsed differently
2184test "std.zon arrays and slices" {1996test "std.zon arrays and slices" {
2185 const gpa = std.testing.allocator;1997 const gpa = std.testing.allocator;
1998 var arena_allocator: ArenaAllocator = .init(gpa);
1999 defer arena_allocator.deinit();
2000 const arena = arena_allocator.allocator();
21862001
2187 // Literals2002 // Literals
2188 {2003 {
...@@ -2236,50 +2051,50 @@ test "std.zon arrays and slices" {...@@ -2236,50 +2051,50 @@ test "std.zon arrays and slices" {
2236 {2051 {
2237 const zero = try fromSliceAlloc([]const u8, .{2052 const zero = try fromSliceAlloc([]const u8, .{
2238 .gpa = gpa,2053 .gpa = gpa,
2054 .arena = arena,
2239 .source = ".{}",2055 .source = ".{}",
2240 .diag = null,2056 .diag = null,
2241 });2057 });
2242 defer free(gpa, zero);
2243 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);2058 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);
22442059
2245 const one = try fromSliceAlloc([]u8, .{2060 const one = try fromSliceAlloc([]u8, .{
2246 .gpa = gpa,2061 .gpa = gpa,
2062 .arena = arena,
2247 .source = ".{'a'}",2063 .source = ".{'a'}",
2248 .diag = null,2064 .diag = null,
2249 });2065 });
2250 defer free(gpa, one);
2251 try std.testing.expectEqualSlices(u8, &.{'a'}, one);2066 try std.testing.expectEqualSlices(u8, &.{'a'}, one);
22522067
2253 const two = try fromSliceAlloc([]const u8, .{2068 const two = try fromSliceAlloc([]const u8, .{
2254 .gpa = gpa,2069 .gpa = gpa,
2070 .arena = arena,
2255 .source = ".{'a', 'b'}",2071 .source = ".{'a', 'b'}",
2256 .diag = null,2072 .diag = null,
2257 });2073 });
2258 defer free(gpa, two);
2259 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);2074 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);
22602075
2261 const two_comma = try fromSliceAlloc([]const u8, .{2076 const two_comma = try fromSliceAlloc([]const u8, .{
2262 .gpa = gpa,2077 .gpa = gpa,
2078 .arena = arena,
2263 .source = ".{'a', 'b',}",2079 .source = ".{'a', 'b',}",
2264 .diag = null,2080 .diag = null,
2265 });2081 });
2266 defer free(gpa, two_comma);
2267 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);2082 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);
22682083
2269 const three = try fromSliceAlloc([]u8, .{2084 const three = try fromSliceAlloc([]u8, .{
2270 .gpa = gpa,2085 .gpa = gpa,
2086 .arena = arena,
2271 .source = ".{'a', 'b', 'c'}",2087 .source = ".{'a', 'b', 'c'}",
2272 .diag = null,2088 .diag = null,
2273 });2089 });
2274 defer free(gpa, three);
2275 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);2090 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);
22762091
2277 const sentinel = try fromSliceAlloc([:'z']const u8, .{2092 const sentinel = try fromSliceAlloc([:'z']const u8, .{
2278 .gpa = gpa,2093 .gpa = gpa,
2094 .arena = arena,
2279 .source = ".{'a', 'b', 'c'}",2095 .source = ".{'a', 'b', 'c'}",
2280 .diag = null,2096 .diag = null,
2281 });2097 });
2282 defer free(gpa, sentinel);
2283 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };2098 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };
2284 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);2099 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);
2285 }2100 }
...@@ -2291,10 +2106,10 @@ test "std.zon arrays and slices" {...@@ -2291,10 +2106,10 @@ test "std.zon arrays and slices" {
2291 {2106 {
2292 const parsed = try fromSliceAlloc([1][]const u8, .{2107 const parsed = try fromSliceAlloc([1][]const u8, .{
2293 .gpa = gpa,2108 .gpa = gpa,
2109 .arena = arena,
2294 .source = ".{\"abc\"}",2110 .source = ".{\"abc\"}",
2295 .diag = null,2111 .diag = null,
2296 });2112 });
2297 defer free(gpa, parsed);
2298 const expected: [1][]const u8 = .{"abc"};2113 const expected: [1][]const u8 = .{"abc"};
2299 try std.testing.expectEqualDeep(expected, parsed);2114 try std.testing.expectEqualDeep(expected, parsed);
2300 }2115 }
...@@ -2303,10 +2118,10 @@ test "std.zon arrays and slices" {...@@ -2303,10 +2118,10 @@ test "std.zon arrays and slices" {
2303 {2118 {
2304 const parsed = try fromSliceAlloc([]const []const u8, .{2119 const parsed = try fromSliceAlloc([]const []const u8, .{
2305 .gpa = gpa,2120 .gpa = gpa,
2121 .arena = arena,
2306 .source = ".{\"abc\"}",2122 .source = ".{\"abc\"}",
2307 .diag = null,2123 .diag = null,
2308 });2124 });
2309 defer free(gpa, parsed);
2310 const expected: []const []const u8 = &.{"abc"};2125 const expected: []const []const u8 = &.{"abc"};
2311 try std.testing.expectEqualDeep(expected, parsed);2126 try std.testing.expectEqualDeep(expected, parsed);
2312 }2127 }
...@@ -2330,10 +2145,10 @@ test "std.zon arrays and slices" {...@@ -2330,10 +2145,10 @@ test "std.zon arrays and slices" {
2330 {2145 {
2331 const sentinel = try fromSliceAlloc([:2]align(4) u8, .{2146 const sentinel = try fromSliceAlloc([:2]align(4) u8, .{
2332 .gpa = gpa,2147 .gpa = gpa,
2148 .arena = arena,
2333 .source = ".{1}",2149 .source = ".{1}",
2334 .diag = null,2150 .diag = null,
2335 });2151 });
2336 defer free(gpa, sentinel);
2337 try std.testing.expectEqual(@as(usize, 1), sentinel.len);2152 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
2338 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);2153 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
2339 try std.testing.expectEqual(@as(u8, 2), sentinel[1]);2154 try std.testing.expectEqual(@as(u8, 2), sentinel[1]);
...@@ -2342,11 +2157,14 @@ test "std.zon arrays and slices" {...@@ -2342,11 +2157,14 @@ test "std.zon arrays and slices" {
23422157
2343 // Expect 0 find 32158 // Expect 0 find 3
2344 {2159 {
2345 var diag: Diagnostics = .{};2160 var diag: Diagnostics = .init(arena);
2346 defer diag.deinit(gpa);
2347 try std.testing.expectError(2161 try std.testing.expectError(
2348 error.ParseZon,2162 error.ParseZon,
2349 fromSlice([0]u8, .{ .gpa = gpa, .source = ".{'a', 'b', 'c'}", .diag = &diag }),2163 fromSlice([0]u8, .{
2164 .gpa = gpa,
2165 .source = ".{'a', 'b', 'c'}",
2166 .diag = &diag,
2167 }),
2350 );2168 );
2351 try std.testing.expectFmt(2169 try std.testing.expectFmt(
2352 "1:3: error: index 0 outside of array of length 0\n",2170 "1:3: error: index 0 outside of array of length 0\n",
...@@ -2357,11 +2175,14 @@ test "std.zon arrays and slices" {...@@ -2357,11 +2175,14 @@ test "std.zon arrays and slices" {
23572175
2358 // Expect 1 find 22176 // Expect 1 find 2
2359 {2177 {
2360 var diag: Diagnostics = .{};2178 var diag: Diagnostics = .init(arena);
2361 defer diag.deinit(gpa);
2362 try std.testing.expectError(2179 try std.testing.expectError(
2363 error.ParseZon,2180 error.ParseZon,
2364 fromSlice([1]u8, .{ .gpa = gpa, .source = ".{'a', 'b'}", .diag = &diag }),2181 fromSlice([1]u8, .{
2182 .gpa = gpa,
2183 .source = ".{'a', 'b'}",
2184 .diag = &diag,
2185 }),
2365 );2186 );
2366 try std.testing.expectFmt(2187 try std.testing.expectFmt(
2367 "1:8: error: index 1 outside of array of length 1\n",2188 "1:8: error: index 1 outside of array of length 1\n",
...@@ -2372,11 +2193,14 @@ test "std.zon arrays and slices" {...@@ -2372,11 +2193,14 @@ test "std.zon arrays and slices" {
23722193
2373 // Expect 2 find 12194 // Expect 2 find 1
2374 {2195 {
2375 var diag: Diagnostics = .{};2196 var diag: Diagnostics = .init(arena);
2376 defer diag.deinit(gpa);
2377 try std.testing.expectError(2197 try std.testing.expectError(
2378 error.ParseZon,2198 error.ParseZon,
2379 fromSlice([2]u8, .{ .gpa = gpa, .source = ".{'a'}", .diag = &diag }),2199 fromSlice([2]u8, .{
2200 .gpa = gpa,
2201 .source = ".{'a'}",
2202 .diag = &diag,
2203 }),
2380 );2204 );
2381 try std.testing.expectFmt(2205 try std.testing.expectFmt(
2382 "1:2: error: expected 2 array elements; found 1\n",2206 "1:2: error: expected 2 array elements; found 1\n",
...@@ -2387,11 +2211,14 @@ test "std.zon arrays and slices" {...@@ -2387,11 +2211,14 @@ test "std.zon arrays and slices" {
23872211
2388 // Expect 3 find 02212 // Expect 3 find 0
2389 {2213 {
2390 var diag: Diagnostics = .{};2214 var diag: Diagnostics = .init(arena);
2391 defer diag.deinit(gpa);
2392 try std.testing.expectError(2215 try std.testing.expectError(
2393 error.ParseZon,2216 error.ParseZon,
2394 fromSlice([3]u8, .{ .gpa = gpa, .source = ".{}", .diag = &diag }),2217 fromSlice([3]u8, .{
2218 .gpa = gpa,
2219 .source = ".{}",
2220 .diag = &diag,
2221 }),
2395 );2222 );
2396 try std.testing.expectFmt(2223 try std.testing.expectFmt(
2397 "1:2: error: expected 3 array elements; found 0\n",2224 "1:2: error: expected 3 array elements; found 0\n",
...@@ -2404,23 +2231,26 @@ test "std.zon arrays and slices" {...@@ -2404,23 +2231,26 @@ test "std.zon arrays and slices" {
2404 {2231 {
2405 // Array2232 // Array
2406 {2233 {
2407 var diag: Diagnostics = .{};2234 var diag: Diagnostics = .init(arena);
2408 defer diag.deinit(gpa);
2409 try std.testing.expectError(2235 try std.testing.expectError(
2410 error.ParseZon,2236 error.ParseZon,
2411 fromSlice([3]bool, .{ .gpa = gpa, .source = ".{'a', 'b', 'c'}", .diag = &diag }),2237 fromSlice([3]bool, .{
2238 .gpa = gpa,
2239 .source = ".{'a', 'b', 'c'}",
2240 .diag = &diag,
2241 }),
2412 );2242 );
2413 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});2243 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
2414 }2244 }
24152245
2416 // Slice2246 // Slice
2417 {2247 {
2418 var diag: Diagnostics = .{};2248 var diag: Diagnostics = .init(arena);
2419 defer diag.deinit(gpa);
2420 try std.testing.expectError(2249 try std.testing.expectError(
2421 error.ParseZon,2250 error.ParseZon,
2422 fromSliceAlloc([]bool, .{2251 fromSliceAlloc([]bool, .{
2423 .gpa = gpa,2252 .gpa = gpa,
2253 .arena = arena,
2424 .source = ".{'a', 'b', 'c'}",2254 .source = ".{'a', 'b', 'c'}",
2425 .diag = &diag,2255 .diag = &diag,
2426 }),2256 }),
...@@ -2433,22 +2263,24 @@ test "std.zon arrays and slices" {...@@ -2433,22 +2263,24 @@ test "std.zon arrays and slices" {
2433 {2263 {
2434 // Array2264 // Array
2435 {2265 {
2436 var diag: Diagnostics = .{};2266 var diag: Diagnostics = .init(arena);
2437 defer diag.deinit(gpa);
2438 try std.testing.expectError(2267 try std.testing.expectError(
2439 error.ParseZon,2268 error.ParseZon,
2440 fromSlice([3]u8, .{ .gpa = gpa, .source = "'a'", .diag = &diag }),2269 fromSlice([3]u8, .{
2270 .gpa = gpa,
2271 .source = "'a'",
2272 .diag = &diag,
2273 }),
2441 );2274 );
2442 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2275 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2443 }2276 }
24442277
2445 // Slice2278 // Slice
2446 {2279 {
2447 var diag: Diagnostics = .{};2280 var diag: Diagnostics = .init(arena);
2448 defer diag.deinit(gpa);
2449 try std.testing.expectError(2281 try std.testing.expectError(
2450 error.ParseZon,2282 error.ParseZon,
2451 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "'a'", .diag = &diag }),2283 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "'a'", .diag = &diag }),
2452 );2284 );
2453 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2285 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2454 }2286 }
...@@ -2456,11 +2288,10 @@ test "std.zon arrays and slices" {...@@ -2456,11 +2288,10 @@ test "std.zon arrays and slices" {
24562288
2457 // Address of is not allowed (indirection for slices in ZON is implicit)2289 // Address of is not allowed (indirection for slices in ZON is implicit)
2458 {2290 {
2459 var diag: Diagnostics = .{};2291 var diag: Diagnostics = .init(arena);
2460 defer diag.deinit(gpa);
2461 try std.testing.expectError(2292 try std.testing.expectError(
2462 error.ParseZon,2293 error.ParseZon,
2463 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = " &.{'a', 'b', 'c'}", .diag = &diag }),2294 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = " &.{'a', 'b', 'c'}", .diag = &diag }),
2464 );2295 );
2465 try std.testing.expectFmt(2296 try std.testing.expectFmt(
2466 "1:3: error: pointers are not available in ZON\n",2297 "1:3: error: pointers are not available in ZON\n",
...@@ -2472,15 +2303,18 @@ test "std.zon arrays and slices" {...@@ -2472,15 +2303,18 @@ test "std.zon arrays and slices" {
24722303
2473test "std.zon string literal" {2304test "std.zon string literal" {
2474 const gpa = std.testing.allocator;2305 const gpa = std.testing.allocator;
2306 var arena_allocator: ArenaAllocator = .init(gpa);
2307 defer arena_allocator.deinit();
2308 const arena = arena_allocator.allocator();
24752309
2476 // Basic string literal2310 // Basic string literal
2477 {2311 {
2478 const parsed = try fromSliceAlloc([]const u8, .{2312 const parsed = try fromSliceAlloc([]const u8, .{
2479 .gpa = gpa,2313 .gpa = gpa,
2314 .arena = arena,
2480 .source = "\"abc\"",2315 .source = "\"abc\"",
2481 .diag = null,2316 .diag = null,
2482 });2317 });
2483 defer free(gpa, parsed);
2484 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);2318 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);
2485 }2319 }
24862320
...@@ -2488,10 +2322,10 @@ test "std.zon string literal" {...@@ -2488,10 +2322,10 @@ test "std.zon string literal" {
2488 {2322 {
2489 const parsed = try fromSliceAlloc([]const u8, .{2323 const parsed = try fromSliceAlloc([]const u8, .{
2490 .gpa = gpa,2324 .gpa = gpa,
2325 .arena = arena,
2491 .source = "\"ab\\nc\"",2326 .source = "\"ab\\nc\"",
2492 .diag = null,2327 .diag = null,
2493 });2328 });
2494 defer free(gpa, parsed);
2495 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);2329 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);
2496 }2330 }
24972331
...@@ -2499,31 +2333,29 @@ test "std.zon string literal" {...@@ -2499,31 +2333,29 @@ test "std.zon string literal" {
2499 {2333 {
2500 const parsed = try fromSliceAlloc([]const u8, .{2334 const parsed = try fromSliceAlloc([]const u8, .{
2501 .gpa = gpa,2335 .gpa = gpa,
2336 .arena = arena,
2502 .source = "\"ab\\x00c\"",2337 .source = "\"ab\\x00c\"",
2503 .diag = null,2338 .diag = null,
2504 });2339 });
2505 defer free(gpa, parsed);
2506 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);2340 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);
2507 }2341 }
25082342
2509 // Passing string literal to a mutable slice2343 // Passing string literal to a mutable slice
2510 {2344 {
2511 {2345 {
2512 var diag: Diagnostics = .{};2346 var diag: Diagnostics = .init(arena);
2513 defer diag.deinit(gpa);
2514 try std.testing.expectError(2347 try std.testing.expectError(
2515 error.ParseZon,2348 error.ParseZon,
2516 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "\"abcd\"", .diag = &diag }),2349 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\"abcd\"", .diag = &diag }),
2517 );2350 );
2518 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2351 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2519 }2352 }
25202353
2521 {2354 {
2522 var diag: Diagnostics = .{};2355 var diag: Diagnostics = .init(arena);
2523 defer diag.deinit(gpa);
2524 try std.testing.expectError(2356 try std.testing.expectError(
2525 error.ParseZon,2357 error.ParseZon,
2526 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "\\\\abcd", .diag = &diag }),2358 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\abcd", .diag = &diag }),
2527 );2359 );
2528 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2360 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2529 }2361 }
...@@ -2536,21 +2368,27 @@ test "std.zon string literal" {...@@ -2536,21 +2368,27 @@ test "std.zon string literal" {
2536 defer ast.deinit(gpa);2368 defer ast.deinit(gpa);
2537 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });2369 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
2538 defer zoir.deinit(gpa);2370 defer zoir.deinit(gpa);
2539 var diag: Diagnostics = .{};2371 var diag: Diagnostics = .init(arena);
2540 defer diag.deinit(gpa);
2541 try std.testing.expectError(2372 try std.testing.expectError(
2542 error.ParseZon,2373 error.ParseZon,
2543 fromSlice([4:0]u8, .{ .gpa = gpa, .source = "\"abcd\"", .diag = &diag }),2374 fromSlice([4:0]u8, .{
2375 .gpa = gpa,
2376 .source = "\"abcd\"",
2377 .diag = &diag,
2378 }),
2544 );2379 );
2545 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2380 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2546 }2381 }
25472382
2548 {2383 {
2549 var diag: Diagnostics = .{};2384 var diag: Diagnostics = .init(arena);
2550 defer diag.deinit(gpa);
2551 try std.testing.expectError(2385 try std.testing.expectError(
2552 error.ParseZon,2386 error.ParseZon,
2553 fromSlice([4:0]u8, .{ .gpa = gpa, .source = "\\\\abcd", .diag = &diag }),2387 fromSlice([4:0]u8, .{
2388 .gpa = gpa,
2389 .source = "\\\\abcd",
2390 .diag = &diag,
2391 }),
2554 );2392 );
2555 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2393 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2556 }2394 }
...@@ -2561,10 +2399,10 @@ test "std.zon string literal" {...@@ -2561,10 +2399,10 @@ test "std.zon string literal" {
2561 {2399 {
2562 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{2400 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{
2563 .gpa = gpa,2401 .gpa = gpa,
2402 .arena = arena,
2564 .source = "\"abc\"",2403 .source = "\"abc\"",
2565 .diag = null,2404 .diag = null,
2566 });2405 });
2567 defer free(gpa, parsed);
2568 try std.testing.expectEqualStrings("abc", parsed);2406 try std.testing.expectEqualStrings("abc", parsed);
2569 try std.testing.expectEqual(@as(u8, 0), parsed[3]);2407 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
2570 }2408 }
...@@ -2572,10 +2410,10 @@ test "std.zon string literal" {...@@ -2572,10 +2410,10 @@ test "std.zon string literal" {
2572 {2410 {
2573 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{2411 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{
2574 .gpa = gpa,2412 .gpa = gpa,
2413 .arena = arena,
2575 .source = "\\\\abc",2414 .source = "\\\\abc",
2576 .diag = null,2415 .diag = null,
2577 });2416 });
2578 defer free(gpa, parsed);
2579 try std.testing.expectEqualStrings("abc", parsed);2417 try std.testing.expectEqualStrings("abc", parsed);
2580 try std.testing.expectEqual(@as(u8, 0), parsed[3]);2418 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
2581 }2419 }
...@@ -2584,21 +2422,19 @@ test "std.zon string literal" {...@@ -2584,21 +2422,19 @@ test "std.zon string literal" {
2584 // Other value terminated slices2422 // Other value terminated slices
2585 {2423 {
2586 {2424 {
2587 var diag: Diagnostics = .{};2425 var diag: Diagnostics = .init(arena);
2588 defer diag.deinit(gpa);
2589 try std.testing.expectError(2426 try std.testing.expectError(
2590 error.ParseZon,2427 error.ParseZon,
2591 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .source = "\"foo\"", .diag = &diag }),2428 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\"foo\"", .diag = &diag }),
2592 );2429 );
2593 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2430 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2594 }2431 }
25952432
2596 {2433 {
2597 var diag: Diagnostics = .{};2434 var diag: Diagnostics = .init(arena);
2598 defer diag.deinit(gpa);
2599 try std.testing.expectError(2435 try std.testing.expectError(
2600 error.ParseZon,2436 error.ParseZon,
2601 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .source = "\\\\foo", .diag = &diag }),2437 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\foo", .diag = &diag }),
2602 );2438 );
2603 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2439 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2604 }2440 }
...@@ -2606,33 +2442,30 @@ test "std.zon string literal" {...@@ -2606,33 +2442,30 @@ test "std.zon string literal" {
26062442
2607 // Expecting string literal, getting something else2443 // Expecting string literal, getting something else
2608 {2444 {
2609 var diag: Diagnostics = .{};2445 var diag: Diagnostics = .init(arena);
2610 defer diag.deinit(gpa);
2611 try std.testing.expectError(2446 try std.testing.expectError(
2612 error.ParseZon,2447 error.ParseZon,
2613 fromSliceAlloc([]const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),2448 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = "true", .diag = &diag }),
2614 );2449 );
2615 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});2450 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
2616 }2451 }
26172452
2618 // Expecting string literal, getting an incompatible tuple2453 // Expecting string literal, getting an incompatible tuple
2619 {2454 {
2620 var diag: Diagnostics = .{};2455 var diag: Diagnostics = .init(arena);
2621 defer diag.deinit(gpa);
2622 try std.testing.expectError(2456 try std.testing.expectError(
2623 error.ParseZon,2457 error.ParseZon,
2624 fromSliceAlloc([]const u8, .{ .gpa = gpa, .source = ".{false}", .diag = &diag }),2458 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = ".{false}", .diag = &diag }),
2625 );2459 );
2626 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});2460 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
2627 }2461 }
26282462
2629 // Invalid string literal2463 // Invalid string literal
2630 {2464 {
2631 var diag: Diagnostics = .{};2465 var diag: Diagnostics = .init(arena);
2632 defer diag.deinit(gpa);
2633 try std.testing.expectError(2466 try std.testing.expectError(
2634 error.ParseZon,2467 error.ParseZon,
2635 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\"\\a\"", .diag = &diag }),2468 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"\\a\"", .diag = &diag }),
2636 );2469 );
2637 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});2470 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
2638 }2471 }
...@@ -2640,21 +2473,19 @@ test "std.zon string literal" {...@@ -2640,21 +2473,19 @@ test "std.zon string literal" {
2640 // Slice wrong child type2473 // Slice wrong child type
2641 {2474 {
2642 {2475 {
2643 var diag: Diagnostics = .{};2476 var diag: Diagnostics = .init(arena);
2644 defer diag.deinit(gpa);
2645 try std.testing.expectError(2477 try std.testing.expectError(
2646 error.ParseZon,2478 error.ParseZon,
2647 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\"a\"", .diag = &diag }),2479 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"a\"", .diag = &diag }),
2648 );2480 );
2649 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2481 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2650 }2482 }
26512483
2652 {2484 {
2653 var diag: Diagnostics = .{};2485 var diag: Diagnostics = .init(arena);
2654 defer diag.deinit(gpa);
2655 try std.testing.expectError(2486 try std.testing.expectError(
2656 error.ParseZon,2487 error.ParseZon,
2657 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\\\\a", .diag = &diag }),2488 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\\\\a", .diag = &diag }),
2658 );2489 );
2659 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});2490 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2660 }2491 }
...@@ -2663,12 +2494,12 @@ test "std.zon string literal" {...@@ -2663,12 +2494,12 @@ test "std.zon string literal" {
2663 // Bad alignment2494 // Bad alignment
2664 {2495 {
2665 {2496 {
2666 var diag: Diagnostics = .{};2497 var diag: Diagnostics = .init(arena);
2667 defer diag.deinit(gpa);
2668 try std.testing.expectError(2498 try std.testing.expectError(
2669 error.ParseZon,2499 error.ParseZon,
2670 fromSliceAlloc([]align(2) const u8, .{2500 fromSliceAlloc([]align(2) const u8, .{
2671 .gpa = gpa,2501 .gpa = gpa,
2502 .arena = arena,
2672 .source = "\"abc\"",2503 .source = "\"abc\"",
2673 .diag = &diag,2504 .diag = &diag,
2674 }),2505 }),
...@@ -2677,12 +2508,12 @@ test "std.zon string literal" {...@@ -2677,12 +2508,12 @@ test "std.zon string literal" {
2677 }2508 }
26782509
2679 {2510 {
2680 var diag: Diagnostics = .{};2511 var diag: Diagnostics = .init(arena);
2681 defer diag.deinit(gpa);
2682 try std.testing.expectError(2512 try std.testing.expectError(
2683 error.ParseZon,2513 error.ParseZon,
2684 fromSliceAlloc([]align(2) const u8, .{2514 fromSliceAlloc([]align(2) const u8, .{
2685 .gpa = gpa,2515 .gpa = gpa,
2516 .arena = arena,
2686 .source = "\\\\abc",2517 .source = "\\\\abc",
2687 .diag = &diag,2518 .diag = &diag,
2688 }),2519 }),
...@@ -2702,6 +2533,7 @@ test "std.zon string literal" {...@@ -2702,6 +2533,7 @@ test "std.zon string literal" {
2702 };2533 };
2703 const parsed = try fromSliceAlloc(S, .{2534 const parsed = try fromSliceAlloc(S, .{
2704 .gpa = gpa,2535 .gpa = gpa,
2536 .arena = arena,
2705 .source =2537 .source =
2706 \\.{2538 \\.{
2707 \\ .message =2539 \\ .message =
...@@ -2722,7 +2554,6 @@ test "std.zon string literal" {...@@ -2722,7 +2554,6 @@ test "std.zon string literal" {
2722 ,2554 ,
2723 .diag = null,2555 .diag = null,
2724 });2556 });
2725 defer free(gpa, parsed);
2726 try std.testing.expectEqualStrings(2557 try std.testing.expectEqualStrings(
2727 "hello, world!\nthis is a multiline string!\n\n...",2558 "hello, world!\nthis is a multiline string!\n\n...",
2728 parsed.message,2559 parsed.message,
...@@ -2735,6 +2566,9 @@ test "std.zon string literal" {...@@ -2735,6 +2566,9 @@ test "std.zon string literal" {
27352566
2736test "std.zon enum literals" {2567test "std.zon enum literals" {
2737 const gpa = std.testing.allocator;2568 const gpa = std.testing.allocator;
2569 var arena_allocator: ArenaAllocator = .init(gpa);
2570 defer arena_allocator.deinit();
2571 const arena = arena_allocator.allocator();
27382572
2739 const Enum = enum {2573 const Enum = enum {
2740 foo,2574 foo,
...@@ -2761,16 +2595,23 @@ test "std.zon enum literals" {...@@ -2761,16 +2595,23 @@ test "std.zon enum literals" {
2761 }));2595 }));
2762 try std.testing.expectEqual(2596 try std.testing.expectEqual(
2763 Enum.@"ab\nc",2597 Enum.@"ab\nc",
2764 try fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"ab\\nc\"", .diag = null }),2598 try fromSlice(Enum, .{
2599 .gpa = gpa,
2600 .source = ".@\"ab\\nc\"",
2601 .diag = null,
2602 }),
2765 );2603 );
27662604
2767 // Bad tag2605 // Bad tag
2768 {2606 {
2769 var diag: Diagnostics = .{};2607 var diag: Diagnostics = .init(arena);
2770 defer diag.deinit(gpa);
2771 try std.testing.expectError(2608 try std.testing.expectError(
2772 error.ParseZon,2609 error.ParseZon,
2773 fromSlice(Enum, .{ .gpa = gpa, .source = ".qux", .diag = &diag }),2610 fromSlice(Enum, .{
2611 .gpa = gpa,
2612 .source = ".qux",
2613 .diag = &diag,
2614 }),
2774 );2615 );
2775 try std.testing.expectFmt(2616 try std.testing.expectFmt(
2776 \\1:2: error: unexpected enum literal 'qux'2617 \\1:2: error: unexpected enum literal 'qux'
...@@ -2784,11 +2625,14 @@ test "std.zon enum literals" {...@@ -2784,11 +2625,14 @@ test "std.zon enum literals" {
27842625
2785 // Bad tag that's too long for parser2626 // Bad tag that's too long for parser
2786 {2627 {
2787 var diag: Diagnostics = .{};2628 var diag: Diagnostics = .init(arena);
2788 defer diag.deinit(gpa);
2789 try std.testing.expectError(2629 try std.testing.expectError(
2790 error.ParseZon,2630 error.ParseZon,
2791 fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"foobarbaz\"", .diag = &diag }),2631 fromSlice(Enum, .{
2632 .gpa = gpa,
2633 .source = ".@\"foobarbaz\"",
2634 .diag = &diag,
2635 }),
2792 );2636 );
2793 try std.testing.expectFmt(2637 try std.testing.expectFmt(
2794 \\1:2: error: unexpected enum literal 'foobarbaz'2638 \\1:2: error: unexpected enum literal 'foobarbaz'
...@@ -2802,22 +2646,28 @@ test "std.zon enum literals" {...@@ -2802,22 +2646,28 @@ test "std.zon enum literals" {
28022646
2803 // Bad type2647 // Bad type
2804 {2648 {
2805 var diag: Diagnostics = .{};2649 var diag: Diagnostics = .init(arena);
2806 defer diag.deinit(gpa);
2807 try std.testing.expectError(2650 try std.testing.expectError(
2808 error.ParseZon,2651 error.ParseZon,
2809 fromSlice(Enum, .{ .gpa = gpa, .source = "true", .diag = &diag }),2652 fromSlice(Enum, .{
2653 .gpa = gpa,
2654 .source = "true",
2655 .diag = &diag,
2656 }),
2810 );2657 );
2811 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{diag});2658 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{diag});
2812 }2659 }
28132660
2814 // Test embedded nulls in an identifier2661 // Test embedded nulls in an identifier
2815 {2662 {
2816 var diag: Diagnostics = .{};2663 var diag: Diagnostics = .init(arena);
2817 defer diag.deinit(gpa);
2818 try std.testing.expectError(2664 try std.testing.expectError(
2819 error.ParseZon,2665 error.ParseZon,
2820 fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"\\x00\"", .diag = &diag }),2666 fromSlice(Enum, .{
2667 .gpa = gpa,
2668 .source = ".@\"\\x00\"",
2669 .diag = &diag,
2670 }),
2821 );2671 );
2822 try std.testing.expectFmt(2672 try std.testing.expectFmt(
2823 "1:2: error: identifier cannot contain null bytes\n",2673 "1:2: error: identifier cannot contain null bytes\n",
...@@ -2829,6 +2679,9 @@ test "std.zon enum literals" {...@@ -2829,6 +2679,9 @@ test "std.zon enum literals" {
28292679
2830test "std.zon parse bool" {2680test "std.zon parse bool" {
2831 const gpa = std.testing.allocator;2681 const gpa = std.testing.allocator;
2682 var arena_allocator: ArenaAllocator = .init(gpa);
2683 defer arena_allocator.deinit();
2684 const arena = arena_allocator.allocator();
28322685
2833 // Correct bools2686 // Correct bools
2834 try std.testing.expectEqual(true, try fromSlice(bool, .{2687 try std.testing.expectEqual(true, try fromSlice(bool, .{
...@@ -2844,11 +2697,14 @@ test "std.zon parse bool" {...@@ -2844,11 +2697,14 @@ test "std.zon parse bool" {
28442697
2845 // Errors2698 // Errors
2846 {2699 {
2847 var diag: Diagnostics = .{};2700 var diag: Diagnostics = .init(arena);
2848 defer diag.deinit(gpa);
2849 try std.testing.expectError(2701 try std.testing.expectError(
2850 error.ParseZon,2702 error.ParseZon,
2851 fromSlice(bool, .{ .gpa = gpa, .source = " foo", .diag = &diag }),2703 fromSlice(bool, .{
2704 .gpa = gpa,
2705 .source = " foo",
2706 .diag = &diag,
2707 }),
2852 );2708 );
2853 try std.testing.expectFmt(2709 try std.testing.expectFmt(
2854 \\1:2: error: invalid expression2710 \\1:2: error: invalid expression
...@@ -2858,8 +2714,7 @@ test "std.zon parse bool" {...@@ -2858,8 +2714,7 @@ test "std.zon parse bool" {
2858 , "{f}", .{diag});2714 , "{f}", .{diag});
2859 }2715 }
2860 {2716 {
2861 var diag: Diagnostics = .{};2717 var diag: Diagnostics = .init(arena);
2862 defer diag.deinit(gpa);
2863 try std.testing.expectError(error.ParseZon, fromSlice(bool, .{2718 try std.testing.expectError(error.ParseZon, fromSlice(bool, .{
2864 .gpa = gpa,2719 .gpa = gpa,
2865 .source = "123",2720 .source = "123",
...@@ -2893,6 +2748,9 @@ test "std.zon intFromFloatExact" {...@@ -2893,6 +2748,9 @@ test "std.zon intFromFloatExact" {
28932748
2894test "std.zon parse int" {2749test "std.zon parse int" {
2895 const gpa = std.testing.allocator;2750 const gpa = std.testing.allocator;
2751 var arena_allocator: ArenaAllocator = .init(gpa);
2752 defer arena_allocator.deinit();
2753 const arena = arena_allocator.allocator();
28962754
2897 // Test various numbers and types2755 // Test various numbers and types
2898 try std.testing.expectEqual(@as(u8, 10), try fromSlice(u8, .{2756 try std.testing.expectEqual(@as(u8, 10), try fromSlice(u8, .{
...@@ -2984,8 +2842,7 @@ test "std.zon parse int" {...@@ -2984,8 +2842,7 @@ test "std.zon parse int" {
2984 }),2842 }),
2985 );2843 );
2986 {2844 {
2987 var diag: Diagnostics = .{};2845 var diag: Diagnostics = .init(arena);
2988 defer diag.deinit(gpa);
2989 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{2846 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
2990 .gpa = gpa,2847 .gpa = gpa,
2991 .source = "36893488147419103232",2848 .source = "36893488147419103232",
...@@ -2998,8 +2855,7 @@ test "std.zon parse int" {...@@ -2998,8 +2855,7 @@ test "std.zon parse int" {
2998 );2855 );
2999 }2856 }
3000 {2857 {
3001 var diag: Diagnostics = .{};2858 var diag: Diagnostics = .init(arena);
3002 defer diag.deinit(gpa);
3003 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{2859 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
3004 .gpa = gpa,2860 .gpa = gpa,
3005 .source = "-36893488147419103233",2861 .source = "-36893488147419103233",
...@@ -3105,8 +2961,7 @@ test "std.zon parse int" {...@@ -3105,8 +2961,7 @@ test "std.zon parse int" {
31052961
3106 // Number with invalid character in the middle2962 // Number with invalid character in the middle
3107 {2963 {
3108 var diag: Diagnostics = .{};2964 var diag: Diagnostics = .init(arena);
3109 defer diag.deinit(gpa);
3110 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{2965 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3111 .gpa = gpa,2966 .gpa = gpa,
3112 .source = "32a32",2967 .source = "32a32",
...@@ -3121,8 +2976,7 @@ test "std.zon parse int" {...@@ -3121,8 +2976,7 @@ test "std.zon parse int" {
31212976
3122 // Failing to parse as int2977 // Failing to parse as int
3123 {2978 {
3124 var diag: Diagnostics = .{};2979 var diag: Diagnostics = .init(arena);
3125 defer diag.deinit(gpa);
3126 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{2980 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3127 .gpa = gpa,2981 .gpa = gpa,
3128 .source = "true",2982 .source = "true",
...@@ -3133,8 +2987,7 @@ test "std.zon parse int" {...@@ -3133,8 +2987,7 @@ test "std.zon parse int" {
31332987
3134 // Failing because an int is out of range2988 // Failing because an int is out of range
3135 {2989 {
3136 var diag: Diagnostics = .{};2990 var diag: Diagnostics = .init(arena);
3137 defer diag.deinit(gpa);
3138 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{2991 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3139 .gpa = gpa,2992 .gpa = gpa,
3140 .source = "256",2993 .source = "256",
...@@ -3149,8 +3002,7 @@ test "std.zon parse int" {...@@ -3149,8 +3002,7 @@ test "std.zon parse int" {
31493002
3150 // Failing because a negative int is out of range3003 // Failing because a negative int is out of range
3151 {3004 {
3152 var diag: Diagnostics = .{};3005 var diag: Diagnostics = .init(arena);
3153 defer diag.deinit(gpa);
3154 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3006 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3155 .gpa = gpa,3007 .gpa = gpa,
3156 .source = "-129",3008 .source = "-129",
...@@ -3165,8 +3017,7 @@ test "std.zon parse int" {...@@ -3165,8 +3017,7 @@ test "std.zon parse int" {
31653017
3166 // Failing because an unsigned int is negative3018 // Failing because an unsigned int is negative
3167 {3019 {
3168 var diag: Diagnostics = .{};3020 var diag: Diagnostics = .init(arena);
3169 defer diag.deinit(gpa);
3170 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{3021 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3171 .gpa = gpa,3022 .gpa = gpa,
3172 .source = "-1",3023 .source = "-1",
...@@ -3181,8 +3032,7 @@ test "std.zon parse int" {...@@ -3181,8 +3032,7 @@ test "std.zon parse int" {
31813032
3182 // Failing because a float is non-whole3033 // Failing because a float is non-whole
3183 {3034 {
3184 var diag: Diagnostics = .{};3035 var diag: Diagnostics = .init(arena);
3185 defer diag.deinit(gpa);
3186 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{3036 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3187 .gpa = gpa,3037 .gpa = gpa,
3188 .source = "1.5",3038 .source = "1.5",
...@@ -3197,8 +3047,7 @@ test "std.zon parse int" {...@@ -3197,8 +3047,7 @@ test "std.zon parse int" {
31973047
3198 // Failing because a float is negative3048 // Failing because a float is negative
3199 {3049 {
3200 var diag: Diagnostics = .{};3050 var diag: Diagnostics = .init(arena);
3201 defer diag.deinit(gpa);
3202 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{3051 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3203 .gpa = gpa,3052 .gpa = gpa,
3204 .source = "-1.0",3053 .source = "-1.0",
...@@ -3213,8 +3062,7 @@ test "std.zon parse int" {...@@ -3213,8 +3062,7 @@ test "std.zon parse int" {
32133062
3214 // Negative integer zero3063 // Negative integer zero
3215 {3064 {
3216 var diag: Diagnostics = .{};3065 var diag: Diagnostics = .init(arena);
3217 defer diag.deinit(gpa);
3218 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3066 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3219 .gpa = gpa,3067 .gpa = gpa,
3220 .source = "-0",3068 .source = "-0",
...@@ -3230,8 +3078,7 @@ test "std.zon parse int" {...@@ -3230,8 +3078,7 @@ test "std.zon parse int" {
32303078
3231 // Negative integer zero casted to float3079 // Negative integer zero casted to float
3232 {3080 {
3233 var diag: Diagnostics = .{};3081 var diag: Diagnostics = .init(arena);
3234 defer diag.deinit(gpa);
3235 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{3082 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3236 .gpa = gpa,3083 .gpa = gpa,
3237 .source = "-0",3084 .source = "-0",
...@@ -3261,8 +3108,7 @@ test "std.zon parse int" {...@@ -3261,8 +3108,7 @@ test "std.zon parse int" {
32613108
3262 // Double negation is not allowed3109 // Double negation is not allowed
3263 {3110 {
3264 var diag: Diagnostics = .{};3111 var diag: Diagnostics = .init(arena);
3265 defer diag.deinit(gpa);
3266 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3112 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3267 .gpa = gpa,3113 .gpa = gpa,
3268 .source = "--2",3114 .source = "--2",
...@@ -3276,11 +3122,14 @@ test "std.zon parse int" {...@@ -3276,11 +3122,14 @@ test "std.zon parse int" {
3276 }3122 }
32773123
3278 {3124 {
3279 var diag: Diagnostics = .{};3125 var diag: Diagnostics = .init(arena);
3280 defer diag.deinit(gpa);
3281 try std.testing.expectError(3126 try std.testing.expectError(
3282 error.ParseZon,3127 error.ParseZon,
3283 fromSlice(f32, .{ .gpa = gpa, .source = "--2.0", .diag = &diag }),3128 fromSlice(f32, .{
3129 .gpa = gpa,
3130 .source = "--2.0",
3131 .diag = &diag,
3132 }),
3284 );3133 );
3285 try std.testing.expectFmt(3134 try std.testing.expectFmt(
3286 "1:1: error: expected number or 'inf' after '-'\n",3135 "1:1: error: expected number or 'inf' after '-'\n",
...@@ -3291,8 +3140,7 @@ test "std.zon parse int" {...@@ -3291,8 +3140,7 @@ test "std.zon parse int" {
32913140
3292 // Invalid int literal3141 // Invalid int literal
3293 {3142 {
3294 var diag: Diagnostics = .{};3143 var diag: Diagnostics = .init(arena);
3295 defer diag.deinit(gpa);
3296 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{3144 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3297 .gpa = gpa,3145 .gpa = gpa,
3298 .source = "0xg",3146 .source = "0xg",
...@@ -3303,8 +3151,7 @@ test "std.zon parse int" {...@@ -3303,8 +3151,7 @@ test "std.zon parse int" {
33033151
3304 // Notes on invalid int literal3152 // Notes on invalid int literal
3305 {3153 {
3306 var diag: Diagnostics = .{};3154 var diag: Diagnostics = .init(arena);
3307 defer diag.deinit(gpa);
3308 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{3155 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3309 .gpa = gpa,3156 .gpa = gpa,
3310 .source = "0123",3157 .source = "0123",
...@@ -3320,10 +3167,12 @@ test "std.zon parse int" {...@@ -3320,10 +3167,12 @@ test "std.zon parse int" {
33203167
3321test "std.zon negative char" {3168test "std.zon negative char" {
3322 const gpa = std.testing.allocator;3169 const gpa = std.testing.allocator;
3170 var arena_allocator: ArenaAllocator = .init(gpa);
3171 defer arena_allocator.deinit();
3172 const arena = arena_allocator.allocator();
33233173
3324 {3174 {
3325 var diag: Diagnostics = .{};3175 var diag: Diagnostics = .init(arena);
3326 defer diag.deinit(gpa);
3327 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{3176 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3328 .gpa = gpa,3177 .gpa = gpa,
3329 .source = "-'a'",3178 .source = "-'a'",
...@@ -3336,8 +3185,7 @@ test "std.zon negative char" {...@@ -3336,8 +3185,7 @@ test "std.zon negative char" {
3336 );3185 );
3337 }3186 }
3338 {3187 {
3339 var diag: Diagnostics = .{};3188 var diag: Diagnostics = .init(arena);
3340 defer diag.deinit(gpa);
3341 try std.testing.expectError(error.ParseZon, fromSlice(i16, .{3189 try std.testing.expectError(error.ParseZon, fromSlice(i16, .{
3342 .gpa = gpa,3190 .gpa = gpa,
3343 .source = "-'a'",3191 .source = "-'a'",
...@@ -3353,6 +3201,9 @@ test "std.zon negative char" {...@@ -3353,6 +3201,9 @@ test "std.zon negative char" {
33533201
3354test "std.zon parse float" {3202test "std.zon parse float" {
3355 const gpa = std.testing.allocator;3203 const gpa = std.testing.allocator;
3204 var arena_allocator: ArenaAllocator = .init(gpa);
3205 defer arena_allocator.deinit();
3206 const arena = arena_allocator.allocator();
33563207
3357 // Test decimals3208 // Test decimals
3358 try std.testing.expectEqual(@as(f16, 0.5), try fromSlice(f16, .{3209 try std.testing.expectEqual(@as(f16, 0.5), try fromSlice(f16, .{
...@@ -3362,11 +3213,19 @@ test "std.zon parse float" {...@@ -3362,11 +3213,19 @@ test "std.zon parse float" {
3362 }));3213 }));
3363 try std.testing.expectEqual(3214 try std.testing.expectEqual(
3364 @as(f32, 123.456),3215 @as(f32, 123.456),
3365 try fromSlice(f32, .{ .gpa = gpa, .source = "123.456", .diag = null }),3216 try fromSlice(f32, .{
3217 .gpa = gpa,
3218 .source = "123.456",
3219 .diag = null,
3220 }),
3366 );3221 );
3367 try std.testing.expectEqual(3222 try std.testing.expectEqual(
3368 @as(f64, -123.456),3223 @as(f64, -123.456),
3369 try fromSlice(f64, .{ .gpa = gpa, .source = "-123.456", .diag = null }),3224 try fromSlice(f64, .{
3225 .gpa = gpa,
3226 .source = "-123.456",
3227 .diag = null,
3228 }),
3370 );3229 );
3371 try std.testing.expectEqual(@as(f128, 42.5), try fromSlice(f128, .{3230 try std.testing.expectEqual(@as(f128, 42.5), try fromSlice(f128, .{
3372 .gpa = gpa,3231 .gpa = gpa,
...@@ -3491,8 +3350,7 @@ test "std.zon parse float" {...@@ -3491,8 +3350,7 @@ test "std.zon parse float" {
34913350
3492 // Negative nan not allowed3351 // Negative nan not allowed
3493 {3352 {
3494 var diag: Diagnostics = .{};3353 var diag: Diagnostics = .init(arena);
3495 defer diag.deinit(gpa);
3496 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{3354 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3497 .gpa = gpa,3355 .gpa = gpa,
3498 .source = "-nan",3356 .source = "-nan",
...@@ -3507,8 +3365,7 @@ test "std.zon parse float" {...@@ -3507,8 +3365,7 @@ test "std.zon parse float" {
35073365
3508 // nan as int not allowed3366 // nan as int not allowed
3509 {3367 {
3510 var diag: Diagnostics = .{};3368 var diag: Diagnostics = .init(arena);
3511 defer diag.deinit(gpa);
3512 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3369 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3513 .gpa = gpa,3370 .gpa = gpa,
3514 .source = "nan",3371 .source = "nan",
...@@ -3519,8 +3376,7 @@ test "std.zon parse float" {...@@ -3519,8 +3376,7 @@ test "std.zon parse float" {
35193376
3520 // nan as int not allowed3377 // nan as int not allowed
3521 {3378 {
3522 var diag: Diagnostics = .{};3379 var diag: Diagnostics = .init(arena);
3523 defer diag.deinit(gpa);
3524 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3380 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3525 .gpa = gpa,3381 .gpa = gpa,
3526 .source = "nan",3382 .source = "nan",
...@@ -3531,8 +3387,7 @@ test "std.zon parse float" {...@@ -3531,8 +3387,7 @@ test "std.zon parse float" {
35313387
3532 // inf as int not allowed3388 // inf as int not allowed
3533 {3389 {
3534 var diag: Diagnostics = .{};3390 var diag: Diagnostics = .init(arena);
3535 defer diag.deinit(gpa);
3536 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3391 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3537 .gpa = gpa,3392 .gpa = gpa,
3538 .source = "inf",3393 .source = "inf",
...@@ -3543,8 +3398,7 @@ test "std.zon parse float" {...@@ -3543,8 +3398,7 @@ test "std.zon parse float" {
35433398
3544 // -inf as int not allowed3399 // -inf as int not allowed
3545 {3400 {
3546 var diag: Diagnostics = .{};3401 var diag: Diagnostics = .init(arena);
3547 defer diag.deinit(gpa);
3548 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{3402 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3549 .gpa = gpa,3403 .gpa = gpa,
3550 .source = "-inf",3404 .source = "-inf",
...@@ -3555,8 +3409,7 @@ test "std.zon parse float" {...@@ -3555,8 +3409,7 @@ test "std.zon parse float" {
35553409
3556 // Bad identifier as float3410 // Bad identifier as float
3557 {3411 {
3558 var diag: Diagnostics = .{};3412 var diag: Diagnostics = .init(arena);
3559 defer diag.deinit(gpa);
3560 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{3413 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3561 .gpa = gpa,3414 .gpa = gpa,
3562 .source = "foo",3415 .source = "foo",
...@@ -3571,8 +3424,7 @@ test "std.zon parse float" {...@@ -3571,8 +3424,7 @@ test "std.zon parse float" {
3571 }3424 }
35723425
3573 {3426 {
3574 var diag: Diagnostics = .{};3427 var diag: Diagnostics = .init(arena);
3575 defer diag.deinit(gpa);
3576 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{3428 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3577 .gpa = gpa,3429 .gpa = gpa,
3578 .source = "-foo",3430 .source = "-foo",
...@@ -3587,17 +3439,25 @@ test "std.zon parse float" {...@@ -3587,17 +3439,25 @@ test "std.zon parse float" {
35873439
3588 // Non float as float3440 // Non float as float
3589 {3441 {
3590 var diag: Diagnostics = .{};3442 var diag: Diagnostics = .init(arena);
3591 defer diag.deinit(gpa);
3592 try std.testing.expectError(3443 try std.testing.expectError(
3593 error.ParseZon,3444 error.ParseZon,
3594 fromSlice(f32, .{ .gpa = gpa, .source = "\"foo\"", .diag = &diag }),3445 fromSlice(f32, .{
3446 .gpa = gpa,
3447 .source = "\"foo\"",
3448 .diag = &diag,
3449 }),
3595 );3450 );
3596 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{diag});3451 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{diag});
3597 }3452 }
3598}3453}
35993454
3600test "std.zon free on error" {3455test "std.zon free on error" {
3456 const gpa = std.testing.allocator;
3457 var arena_allocator: ArenaAllocator = .init(gpa);
3458 defer arena_allocator.deinit();
3459 const arena = arena_allocator.allocator();
3460
3601 // Test freeing partially allocated structs3461 // Test freeing partially allocated structs
3602 {3462 {
3603 const Struct = struct {3463 const Struct = struct {
...@@ -3606,7 +3466,8 @@ test "std.zon free on error" {...@@ -3606,7 +3466,8 @@ test "std.zon free on error" {
3606 z: bool,3466 z: bool,
3607 };3467 };
3608 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{3468 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3609 .gpa = std.testing.allocator,3469 .gpa = gpa,
3470 .arena = arena,
3610 .source =3471 .source =
3611 \\.{3472 \\.{
3612 \\ .x = "hello",3473 \\ .x = "hello",
...@@ -3626,7 +3487,8 @@ test "std.zon free on error" {...@@ -3626,7 +3487,8 @@ test "std.zon free on error" {
3626 bool,3487 bool,
3627 };3488 };
3628 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{3489 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3629 .gpa = std.testing.allocator,3490 .gpa = gpa,
3491 .arena = arena,
3630 .source =3492 .source =
3631 \\.{3493 \\.{
3632 \\ "hello",3494 \\ "hello",
...@@ -3639,58 +3501,55 @@ test "std.zon free on error" {...@@ -3639,58 +3501,55 @@ test "std.zon free on error" {
3639 }3501 }
36403502
3641 // Test freeing structs with missing fields3503 // Test freeing structs with missing fields
3642 {3504 const Struct = struct {
3643 const Struct = struct {3505 x: []const u8,
3644 x: []const u8,3506 y: bool,
3645 y: bool,3507 };
3646 };3508 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3647 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{3509 .gpa = gpa,
3648 .gpa = std.testing.allocator,3510 .arena = arena,
3649 .source =3511 .source =
3650 \\.{3512 \\.{
3651 \\ .x = "hello",3513 \\ .x = "hello",
3652 \\}3514 \\}
3653 ,3515 ,
3654 .diag = null,3516 .diag = null,
3655 }));3517 }));
3656 }
36573518
3658 // Test freeing partially allocated arrays3519 // Test freeing partially allocated arrays
3659 {3520 try std.testing.expectError(error.ParseZon, fromSliceAlloc([3][]const u8, .{
3660 try std.testing.expectError(error.ParseZon, fromSliceAlloc([3][]const u8, .{3521 .gpa = gpa,
3661 .gpa = std.testing.allocator,3522 .arena = arena,
3662 .source =3523 .source =
3663 \\.{3524 \\.{
3664 \\ "hello",3525 \\ "hello",
3665 \\ false,3526 \\ false,
3666 \\ false,3527 \\ false,
3667 \\}3528 \\}
3668 ,3529 ,
3669 .diag = null,3530 .diag = null,
3670 }));3531 }));
3671 }
36723532
3673 // Test freeing partially allocated slices3533 // Test freeing partially allocated slices
3674 {3534 try std.testing.expectError(error.ParseZon, fromSliceAlloc([][]const u8, .{
3675 try std.testing.expectError(error.ParseZon, fromSliceAlloc([][]const u8, .{3535 .gpa = gpa,
3676 .gpa = std.testing.allocator,3536 .arena = arena,
3677 .source =3537 .source =
3678 \\.{3538 \\.{
3679 \\ "hello",3539 \\ "hello",
3680 \\ "world",3540 \\ "world",
3681 \\ false,3541 \\ false,
3682 \\}3542 \\}
3683 ,3543 ,
3684 .diag = null,3544 .diag = null,
3685 }));3545 }));
3686 }
36873546
3688 // We can parse types that can't be freed, as long as they contain no allocations, e.g. untagged3547 // We can parse types that can't be freed, as long as they contain no allocations, e.g. untagged
3689 // unions.3548 // unions.
3690 try std.testing.expectEqual(3549 try std.testing.expectEqual(
3691 @as(f32, 1.5),3550 @as(f32, 1.5),
3692 (try fromSlice(union { x: f32 }, .{3551 (try fromSlice(union { x: f32 }, .{
3693 .gpa = std.testing.allocator,3552 .gpa = gpa,
3694 .source = ".{ .x = 1.5 }",3553 .source = ".{ .x = 1.5 }",
3695 .diag = null,3554 .diag = null,
3696 })).x,3555 })).x,
...@@ -3700,80 +3559,13 @@ test "std.zon free on error" {...@@ -3700,80 +3559,13 @@ test "std.zon free on error" {
3700 // the allocation, as is the case here.3559 // the allocation, as is the case here.
3701 {3560 {
3702 const result = try fromSliceAlloc(union { x: []const u8 }, .{3561 const result = try fromSliceAlloc(union { x: []const u8 }, .{
3703 .gpa = std.testing.allocator,3562 .gpa = gpa,
3563 .arena = arena,
3704 .source = ".{ .x = \"foo\" }",3564 .source = ".{ .x = \"foo\" }",
3705 .diag = null,3565 .diag = null,
3706 });3566 });
3707 defer free(std.testing.allocator, result.x);
3708 try std.testing.expectEqualStrings("foo", result.x);3567 try std.testing.expectEqualStrings("foo", result.x);
3709 }3568 }
3710
3711 // However, if it's possible we could get an error requiring we free the value, but the value
3712 // cannot be freed (e.g. untagged unions) then we need to turn off `free_on_error` for it to
3713 // compile.
3714 {
3715 const S = struct {
3716 union { x: []const u8 },
3717 bool,
3718 };
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 });
3725 defer free(std.testing.allocator, result[0].x);
3726 try std.testing.expectEqualStrings("foo", result[0].x);
3727 try std.testing.expect(result[1]);
3728 }
3729
3730 // Again but for structs.
3731 {
3732 const S = struct {
3733 a: union { x: []const u8 },
3734 b: bool,
3735 };
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 });
3742 defer free(std.testing.allocator, result.a.x);
3743 try std.testing.expectEqualStrings("foo", result.a.x);
3744 try std.testing.expect(result.b);
3745 }
3746
3747 // Again but for arrays.
3748 {
3749 const S = [2]union { x: []const u8 };
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 });
3756 defer free(std.testing.allocator, result[0].x);
3757 defer free(std.testing.allocator, result[1].x);
3758 try std.testing.expectEqualStrings("foo", result[0].x);
3759 try std.testing.expectEqualStrings("bar", result[1].x);
3760 }
3761
3762 // Again but for slices.
3763 {
3764 const S = []union { x: []const u8 };
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 });
3771 defer std.testing.allocator.free(result);
3772 defer free(std.testing.allocator, result[0].x);
3773 defer free(std.testing.allocator, result[1].x);
3774 try std.testing.expectEqualStrings("foo", result[0].x);
3775 try std.testing.expectEqualStrings("bar", result[1].x);
3776 }
3777}3569}
37783570
3779test "std.zon vector" {3571test "std.zon vector" {
...@@ -3781,11 +3573,18 @@ test "std.zon vector" {...@@ -3781,11 +3573,18 @@ test "std.zon vector" {
3781 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/259573573 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957
37823574
3783 const gpa = std.testing.allocator;3575 const gpa = std.testing.allocator;
3576 var arena_allocator: ArenaAllocator = .init(gpa);
3577 defer arena_allocator.deinit();
3578 const arena = arena_allocator.allocator();
37843579
3785 // Passing cases3580 // Passing cases
3786 try std.testing.expectEqual(3581 try std.testing.expectEqual(
3787 @Vector(0, bool){},3582 @Vector(0, bool){},
3788 try fromSlice(@Vector(0, bool), .{ .gpa = gpa, .source = ".{}", .diag = null }),3583 try fromSlice(@Vector(0, bool), .{
3584 .gpa = gpa,
3585 .source = ".{}",
3586 .diag = null,
3587 }),
3789 );3588 );
3790 try std.testing.expectEqual(3589 try std.testing.expectEqual(
3791 @Vector(3, bool){ true, false, true },3590 @Vector(3, bool){ true, false, true },
...@@ -3798,7 +3597,11 @@ test "std.zon vector" {...@@ -3798,7 +3597,11 @@ test "std.zon vector" {
37983597
3799 try std.testing.expectEqual(3598 try std.testing.expectEqual(
3800 @Vector(0, f32){},3599 @Vector(0, f32){},
3801 try fromSlice(@Vector(0, f32), .{ .gpa = gpa, .source = ".{}", .diag = null }),3600 try fromSlice(@Vector(0, f32), .{
3601 .gpa = gpa,
3602 .source = ".{}",
3603 .diag = null,
3604 }),
3802 );3605 );
3803 try std.testing.expectEqual(3606 try std.testing.expectEqual(
3804 @Vector(3, f32){ 1.5, 2.5, 3.5 },3607 @Vector(3, f32){ 1.5, 2.5, 3.5 },
...@@ -3811,11 +3614,19 @@ test "std.zon vector" {...@@ -3811,11 +3614,19 @@ test "std.zon vector" {
38113614
3812 try std.testing.expectEqual(3615 try std.testing.expectEqual(
3813 @Vector(0, u8){},3616 @Vector(0, u8){},
3814 try fromSlice(@Vector(0, u8), .{ .gpa = gpa, .source = ".{}", .diag = null }),3617 try fromSlice(@Vector(0, u8), .{
3618 .gpa = gpa,
3619 .source = ".{}",
3620 .diag = null,
3621 }),
3815 );3622 );
3816 try std.testing.expectEqual(3623 try std.testing.expectEqual(
3817 @Vector(3, u8){ 2, 4, 6 },3624 @Vector(3, u8){ 2, 4, 6 },
3818 try fromSlice(@Vector(3, u8), .{ .gpa = gpa, .source = ".{2, 4, 6}", .diag = null }),3625 try fromSlice(@Vector(3, u8), .{
3626 .gpa = gpa,
3627 .source = ".{2, 4, 6}",
3628 .diag = null,
3629 }),
3819 );3630 );
38203631
3821 {3632 {
...@@ -3823,16 +3634,17 @@ test "std.zon vector" {...@@ -3823,16 +3634,17 @@ test "std.zon vector" {
3823 @Vector(0, *const u8){},3634 @Vector(0, *const u8){},
3824 try fromSliceAlloc(@Vector(0, *const u8), .{3635 try fromSliceAlloc(@Vector(0, *const u8), .{
3825 .gpa = gpa,3636 .gpa = gpa,
3637 .arena = arena,
3826 .source = ".{}",3638 .source = ".{}",
3827 .diag = null,3639 .diag = null,
3828 }),3640 }),
3829 );3641 );
3830 const pointers = try fromSliceAlloc(@Vector(3, *const u8), .{3642 const pointers = try fromSliceAlloc(@Vector(3, *const u8), .{
3831 .gpa = gpa,3643 .gpa = gpa,
3644 .arena = arena,
3832 .source = ".{2, 4, 6}",3645 .source = ".{2, 4, 6}",
3833 .diag = null,3646 .diag = null,
3834 });3647 });
3835 defer free(gpa, pointers);
3836 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);3648 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);
3837 }3649 }
38383650
...@@ -3841,23 +3653,23 @@ test "std.zon vector" {...@@ -3841,23 +3653,23 @@ test "std.zon vector" {
3841 @Vector(0, ?*const u8){},3653 @Vector(0, ?*const u8){},
3842 try fromSliceAlloc(@Vector(0, ?*const u8), .{3654 try fromSliceAlloc(@Vector(0, ?*const u8), .{
3843 .gpa = gpa,3655 .gpa = gpa,
3656 .arena = arena,
3844 .source = ".{}",3657 .source = ".{}",
3845 .diag = null,3658 .diag = null,
3846 }),3659 }),
3847 );3660 );
3848 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), .{3661 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), .{
3849 .gpa = gpa,3662 .gpa = gpa,
3663 .arena = arena,
3850 .source = ".{2, null, 6}",3664 .source = ".{2, null, 6}",
3851 .diag = null,3665 .diag = null,
3852 });3666 });
3853 defer free(gpa, pointers);
3854 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);3667 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);
3855 }3668 }
38563669
3857 // Too few fields3670 // Too few fields
3858 {3671 {
3859 var diag: Diagnostics = .{};3672 var diag: Diagnostics = .init(arena);
3860 defer diag.deinit(gpa);
3861 try std.testing.expectError(3673 try std.testing.expectError(
3862 error.ParseZon,3674 error.ParseZon,
3863 fromSlice(@Vector(2, f32), .{3675 fromSlice(@Vector(2, f32), .{
...@@ -3875,8 +3687,7 @@ test "std.zon vector" {...@@ -3875,8 +3687,7 @@ test "std.zon vector" {
38753687
3876 // Too many fields3688 // Too many fields
3877 {3689 {
3878 var diag: Diagnostics = .{};3690 var diag: Diagnostics = .init(arena);
3879 defer diag.deinit(gpa);
3880 try std.testing.expectError(3691 try std.testing.expectError(
3881 error.ParseZon,3692 error.ParseZon,
3882 fromSlice(@Vector(2, f32), .{3693 fromSlice(@Vector(2, f32), .{
...@@ -3894,8 +3705,7 @@ test "std.zon vector" {...@@ -3894,8 +3705,7 @@ test "std.zon vector" {
38943705
3895 // Wrong type fields3706 // Wrong type fields
3896 {3707 {
3897 var diag: Diagnostics = .{};3708 var diag: Diagnostics = .init(arena);
3898 defer diag.deinit(gpa);
3899 try std.testing.expectError(3709 try std.testing.expectError(
3900 error.ParseZon,3710 error.ParseZon,
3901 fromSlice(@Vector(3, f32), .{3711 fromSlice(@Vector(3, f32), .{
...@@ -3913,23 +3723,26 @@ test "std.zon vector" {...@@ -3913,23 +3723,26 @@ test "std.zon vector" {
39133723
3914 // Wrong type3724 // Wrong type
3915 {3725 {
3916 var diag: Diagnostics = .{};3726 var diag: Diagnostics = .init(arena);
3917 defer diag.deinit(gpa);
3918 try std.testing.expectError(3727 try std.testing.expectError(
3919 error.ParseZon,3728 error.ParseZon,
3920 fromSlice(@Vector(3, u8), .{ .gpa = gpa, .source = "true", .diag = &diag }),3729 fromSlice(@Vector(3, u8), .{
3730 .gpa = gpa,
3731 .source = "true",
3732 .diag = &diag,
3733 }),
3921 );3734 );
3922 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{diag});3735 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{diag});
3923 }3736 }
39243737
3925 // Elements should get freed on error3738 // Elements should get freed on error
3926 {3739 {
3927 var diag: Diagnostics = .{};3740 var diag: Diagnostics = .init(arena);
3928 defer diag.deinit(gpa);
3929 try std.testing.expectError(3741 try std.testing.expectError(
3930 error.ParseZon,3742 error.ParseZon,
3931 fromSliceAlloc(@Vector(3, *u8), .{3743 fromSliceAlloc(@Vector(3, *u8), .{
3932 .gpa = gpa,3744 .gpa = gpa,
3745 .arena = arena,
3933 .source = ".{1, true, 3}",3746 .source = ".{1, true, 3}",
3934 .diag = &diag,3747 .diag = &diag,
3935 }),3748 }),
...@@ -3940,35 +3753,38 @@ test "std.zon vector" {...@@ -3940,35 +3753,38 @@ test "std.zon vector" {
39403753
3941test "std.zon add pointers" {3754test "std.zon add pointers" {
3942 const gpa = std.testing.allocator;3755 const gpa = std.testing.allocator;
3756 var arena_allocator: ArenaAllocator = .init(gpa);
3757 defer arena_allocator.deinit();
3758 const arena = arena_allocator.allocator();
39433759
3944 // Primitive with varying levels of pointers3760 // Primitive with varying levels of pointers
3945 {3761 {
3946 const result = try fromSliceAlloc(*u32, .{3762 const result = try fromSliceAlloc(*u32, .{
3947 .gpa = gpa,3763 .gpa = gpa,
3764 .arena = arena,
3948 .source = "10",3765 .source = "10",
3949 .diag = null,3766 .diag = null,
3950 });3767 });
3951 defer free(gpa, result);
3952 try std.testing.expectEqual(@as(u32, 10), result.*);3768 try std.testing.expectEqual(@as(u32, 10), result.*);
3953 }3769 }
39543770
3955 {3771 {
3956 const result = try fromSliceAlloc(**u32, .{3772 const result = try fromSliceAlloc(**u32, .{
3957 .gpa = gpa,3773 .gpa = gpa,
3774 .arena = arena,
3958 .source = "10",3775 .source = "10",
3959 .diag = null,3776 .diag = null,
3960 });3777 });
3961 defer free(gpa, result);
3962 try std.testing.expectEqual(@as(u32, 10), result.*.*);3778 try std.testing.expectEqual(@as(u32, 10), result.*.*);
3963 }3779 }
39643780
3965 {3781 {
3966 const result = try fromSliceAlloc(***u32, .{3782 const result = try fromSliceAlloc(***u32, .{
3967 .gpa = gpa,3783 .gpa = gpa,
3784 .arena = arena,
3968 .source = "10",3785 .source = "10",
3969 .diag = null,3786 .diag = null,
3970 });3787 });
3971 defer free(gpa, result);
3972 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);3788 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);
3973 }3789 }
39743790
...@@ -3976,90 +3792,90 @@ test "std.zon add pointers" {...@@ -3976,90 +3792,90 @@ test "std.zon add pointers" {
3976 {3792 {
3977 const some = try fromSliceAlloc(?*u32, .{3793 const some = try fromSliceAlloc(?*u32, .{
3978 .gpa = gpa,3794 .gpa = gpa,
3795 .arena = arena,
3979 .source = "10",3796 .source = "10",
3980 .diag = null,3797 .diag = null,
3981 });3798 });
3982 defer free(gpa, some);
3983 try std.testing.expectEqual(@as(u32, 10), some.?.*);3799 try std.testing.expectEqual(@as(u32, 10), some.?.*);
39843800
3985 const none = try fromSliceAlloc(?*u32, .{3801 const none = try fromSliceAlloc(?*u32, .{
3986 .gpa = gpa,3802 .gpa = gpa,
3803 .arena = arena,
3987 .source = "null",3804 .source = "null",
3988 .diag = null,3805 .diag = null,
3989 });3806 });
3990 defer free(gpa, none);
3991 try std.testing.expectEqual(null, none);3807 try std.testing.expectEqual(null, none);
3992 }3808 }
39933809
3994 {3810 {
3995 const some = try fromSliceAlloc(*?u32, .{3811 const some = try fromSliceAlloc(*?u32, .{
3996 .gpa = gpa,3812 .gpa = gpa,
3813 .arena = arena,
3997 .source = "10",3814 .source = "10",
3998 .diag = null,3815 .diag = null,
3999 });3816 });
4000 defer free(gpa, some);
4001 try std.testing.expectEqual(@as(u32, 10), some.*.?);3817 try std.testing.expectEqual(@as(u32, 10), some.*.?);
40023818
4003 const none = try fromSliceAlloc(*?u32, .{3819 const none = try fromSliceAlloc(*?u32, .{
4004 .gpa = gpa,3820 .gpa = gpa,
3821 .arena = arena,
4005 .source = "null",3822 .source = "null",
4006 .diag = null,3823 .diag = null,
4007 });3824 });
4008 defer free(gpa, none);
4009 try std.testing.expectEqual(null, none.*);3825 try std.testing.expectEqual(null, none.*);
4010 }3826 }
40113827
4012 {3828 {
4013 const some = try fromSliceAlloc(?**u32, .{3829 const some = try fromSliceAlloc(?**u32, .{
4014 .gpa = gpa,3830 .gpa = gpa,
3831 .arena = arena,
4015 .source = "10",3832 .source = "10",
4016 .diag = null,3833 .diag = null,
4017 });3834 });
4018 defer free(gpa, some);
4019 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);3835 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);
40203836
4021 const none = try fromSliceAlloc(?**u32, .{3837 const none = try fromSliceAlloc(?**u32, .{
4022 .gpa = gpa,3838 .gpa = gpa,
3839 .arena = arena,
4023 .source = "null",3840 .source = "null",
4024 .diag = null,3841 .diag = null,
4025 });3842 });
4026 defer free(gpa, none);
4027 try std.testing.expectEqual(null, none);3843 try std.testing.expectEqual(null, none);
4028 }3844 }
40293845
4030 {3846 {
4031 const some = try fromSliceAlloc(*?*u32, .{3847 const some = try fromSliceAlloc(*?*u32, .{
4032 .gpa = gpa,3848 .gpa = gpa,
3849 .arena = arena,
4033 .source = "10",3850 .source = "10",
4034 .diag = null,3851 .diag = null,
4035 });3852 });
4036 defer free(gpa, some);
4037 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);3853 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);
40383854
4039 const none = try fromSliceAlloc(*?*u32, .{3855 const none = try fromSliceAlloc(*?*u32, .{
4040 .gpa = gpa,3856 .gpa = gpa,
3857 .arena = arena,
4041 .source = "null",3858 .source = "null",
4042 .diag = null,3859 .diag = null,
4043 });3860 });
4044 defer free(gpa, none);
4045 try std.testing.expectEqual(null, none.*);3861 try std.testing.expectEqual(null, none.*);
4046 }3862 }
40473863
4048 {3864 {
4049 const some = try fromSliceAlloc(**?u32, .{3865 const some = try fromSliceAlloc(**?u32, .{
4050 .gpa = gpa,3866 .gpa = gpa,
3867 .arena = arena,
4051 .source = "10",3868 .source = "10",
4052 .diag = null,3869 .diag = null,
4053 });3870 });
4054 defer free(gpa, some);
4055 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);3871 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);
40563872
4057 const none = try fromSliceAlloc(**?u32, .{3873 const none = try fromSliceAlloc(**?u32, .{
4058 .gpa = gpa,3874 .gpa = gpa,
3875 .arena = arena,
4059 .source = "null",3876 .source = "null",
4060 .diag = null,3877 .diag = null,
4061 });3878 });
4062 defer free(gpa, none);
4063 try std.testing.expectEqual(null, none.*.*);3879 try std.testing.expectEqual(null, none.*.*);
4064 }3880 }
40653881
...@@ -4067,10 +3883,10 @@ test "std.zon add pointers" {...@@ -4067,10 +3883,10 @@ test "std.zon add pointers" {
4067 {3883 {
4068 const result = try fromSliceAlloc(*[3]u8, .{3884 const result = try fromSliceAlloc(*[3]u8, .{
4069 .gpa = gpa,3885 .gpa = gpa,
3886 .arena = arena,
4070 .source = ".{ 1, 2, 3 }",3887 .source = ".{ 1, 2, 3 }",
4071 .diag = null,3888 .diag = null,
4072 });3889 });
4073 defer free(gpa, result);
4074 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);3890 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);
4075 }3891 }
40763892
...@@ -4094,6 +3910,7 @@ test "std.zon add pointers" {...@@ -4094,6 +3910,7 @@ test "std.zon add pointers" {
40943910
4095 const found = try fromSliceAlloc(?*Outer, .{3911 const found = try fromSliceAlloc(?*Outer, .{
4096 .gpa = gpa,3912 .gpa = gpa,
3913 .arena = arena,
4097 .source =3914 .source =
4098 \\.{3915 \\.{
4099 \\ .f1 = .{3916 \\ .f1 = .{
...@@ -4105,39 +3922,46 @@ test "std.zon add pointers" {...@@ -4105,39 +3922,46 @@ test "std.zon add pointers" {
4105 ,3922 ,
4106 .diag = null,3923 .diag = null,
4107 });3924 });
4108 defer free(gpa, found);
41093925
4110 try std.testing.expectEqualDeep(expected, found.?.*);3926 try std.testing.expectEqualDeep(expected, found.?.*);
4111 }3927 }
41123928
4113 // Test that optional types are flattened correctly in errors3929 // Test that optional types are flattened correctly in errors
4114 {3930 {
4115 var diag: Diagnostics = .{};3931 var diag: Diagnostics = .init(arena);
4116 defer diag.deinit(gpa);
4117 try std.testing.expectError(3932 try std.testing.expectError(
4118 error.ParseZon,3933 error.ParseZon,
4119 fromSliceAlloc(*const ?*const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),3934 fromSliceAlloc(*const ?*const u8, .{
3935 .gpa = gpa,
3936 .arena = arena,
3937 .source = "true",
3938 .diag = &diag,
3939 }),
4120 );3940 );
4121 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});3941 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
4122 }3942 }
41233943
4124 {3944 {
4125 var diag: Diagnostics = .{};3945 var diag: Diagnostics = .init(arena);
4126 defer diag.deinit(gpa);
4127 try std.testing.expectError(3946 try std.testing.expectError(
4128 error.ParseZon,3947 error.ParseZon,
4129 fromSliceAlloc(*const ?*const f32, .{ .gpa = gpa, .source = "true", .diag = &diag }),3948 fromSliceAlloc(*const ?*const f32, .{
3949 .gpa = gpa,
3950 .arena = arena,
3951 .source = "true",
3952 .diag = &diag,
3953 }),
4130 );3954 );
4131 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});3955 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
4132 }3956 }
41333957
4134 {3958 {
4135 var diag: Diagnostics = .{};3959 var diag: Diagnostics = .init(arena);
4136 defer diag.deinit(gpa);
4137 try std.testing.expectError(3960 try std.testing.expectError(
4138 error.ParseZon,3961 error.ParseZon,
4139 fromSliceAlloc(*const ?*const @Vector(3, u8), .{3962 fromSliceAlloc(*const ?*const @Vector(3, u8), .{
4140 .gpa = gpa,3963 .gpa = gpa,
3964 .arena = arena,
4141 .source = "true",3965 .source = "true",
4142 .diag = &diag,3966 .diag = &diag,
4143 }),3967 }),
...@@ -4146,101 +3970,141 @@ test "std.zon add pointers" {...@@ -4146,101 +3970,141 @@ test "std.zon add pointers" {
4146 }3970 }
41473971
4148 {3972 {
4149 var diag: Diagnostics = .{};3973 var diag: Diagnostics = .init(arena);
4150 defer diag.deinit(gpa);
4151 try std.testing.expectError(3974 try std.testing.expectError(
4152 error.ParseZon,3975 error.ParseZon,
4153 fromSliceAlloc(*const ?*const bool, .{ .gpa = gpa, .source = "10", .diag = &diag }),3976 fromSliceAlloc(*const ?*const bool, .{
3977 .gpa = gpa,
3978 .arena = arena,
3979 .source = "10",
3980 .diag = &diag,
3981 }),
4154 );3982 );
4155 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});3983 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
4156 }3984 }
41573985
4158 {3986 {
4159 var diag: Diagnostics = .{};3987 var diag: Diagnostics = .init(arena);
4160 defer diag.deinit(gpa);
4161 try std.testing.expectError(3988 try std.testing.expectError(
4162 error.ParseZon,3989 error.ParseZon,
4163 fromSliceAlloc(*const ?*const struct { a: i32 }, .{ .gpa = gpa, .source = "true", .diag = &diag }),3990 fromSliceAlloc(*const ?*const struct { a: i32 }, .{
3991 .gpa = gpa,
3992 .arena = arena,
3993 .source = "true",
3994 .diag = &diag,
3995 }),
4164 );3996 );
4165 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});3997 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
4166 }3998 }
41673999
4168 {4000 {
4169 var diag: Diagnostics = .{};4001 var diag: Diagnostics = .init(arena);
4170 defer diag.deinit(gpa);
4171 try std.testing.expectError(4002 try std.testing.expectError(
4172 error.ParseZon,4003 error.ParseZon,
4173 fromSliceAlloc(*const ?*const struct { i32 }, .{ .gpa = gpa, .source = "true", .diag = &diag }),4004 fromSliceAlloc(*const ?*const struct { i32 }, .{
4005 .gpa = gpa,
4006 .arena = arena,
4007 .source = "true",
4008 .diag = &diag,
4009 }),
4174 );4010 );
4175 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});4011 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
4176 }4012 }
41774013
4178 {4014 {
4179 var diag: Diagnostics = .{};4015 var diag: Diagnostics = .init(arena);
4180 defer diag.deinit(gpa);
4181 try std.testing.expectError(4016 try std.testing.expectError(
4182 error.ParseZon,4017 error.ParseZon,
4183 fromSliceAlloc(*const ?*const union { x: void }, .{ .gpa = gpa, .source = "true", .diag = &diag }),4018 fromSliceAlloc(*const ?*const union { x: void }, .{
4019 .gpa = gpa,
4020 .arena = arena,
4021 .source = "true",
4022 .diag = &diag,
4023 }),
4184 );4024 );
4185 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});4025 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
4186 }4026 }
41874027
4188 {4028 {
4189 var diag: Diagnostics = .{};4029 var diag: Diagnostics = .init(arena);
4190 defer diag.deinit(gpa);
4191 try std.testing.expectError(4030 try std.testing.expectError(
4192 error.ParseZon,4031 error.ParseZon,
4193 fromSliceAlloc(*const ?*const [3]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),4032 fromSliceAlloc(*const ?*const [3]u8, .{
4033 .gpa = gpa,
4034 .arena = arena,
4035 .source = "true",
4036 .diag = &diag,
4037 }),
4194 );4038 );
4195 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});4039 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
4196 }4040 }
41974041
4198 {4042 {
4199 var diag: Diagnostics = .{};4043 var diag: Diagnostics = .init(arena);
4200 defer diag.deinit(gpa);
4201 try std.testing.expectError(4044 try std.testing.expectError(
4202 error.ParseZon,4045 error.ParseZon,
4203 fromSliceAlloc(?[3]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),4046 fromSliceAlloc(?[3]u8, .{
4047 .gpa = gpa,
4048 .arena = arena,
4049 .source = "true",
4050 .diag = &diag,
4051 }),
4204 );4052 );
4205 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});4053 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
4206 }4054 }
42074055
4208 {4056 {
4209 var diag: Diagnostics = .{};4057 var diag: Diagnostics = .init(arena);
4210 defer diag.deinit(gpa);
4211 try std.testing.expectError(4058 try std.testing.expectError(
4212 error.ParseZon,4059 error.ParseZon,
4213 fromSliceAlloc(*const ?*const []u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),4060 fromSliceAlloc(*const ?*const []u8, .{
4061 .gpa = gpa,
4062 .arena = arena,
4063 .source = "true",
4064 .diag = &diag,
4065 }),
4214 );4066 );
4215 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});4067 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
4216 }4068 }
42174069
4218 {4070 {
4219 var diag: Diagnostics = .{};4071 var diag: Diagnostics = .init(arena);
4220 defer diag.deinit(gpa);
4221 try std.testing.expectError(4072 try std.testing.expectError(
4222 error.ParseZon,4073 error.ParseZon,
4223 fromSliceAlloc(?[]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),4074 fromSliceAlloc(?[]u8, .{
4075 .gpa = gpa,
4076 .arena = arena,
4077 .source = "true",
4078 .diag = &diag,
4079 }),
4224 );4080 );
4225 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});4081 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
4226 }4082 }
42274083
4228 {4084 {
4229 var diag: Diagnostics = .{};4085 var diag: Diagnostics = .init(arena);
4230 defer diag.deinit(gpa);
4231 try std.testing.expectError(4086 try std.testing.expectError(
4232 error.ParseZon,4087 error.ParseZon,
4233 fromSliceAlloc(*const ?*const []const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),4088 fromSliceAlloc(*const ?*const []const u8, .{
4089 .gpa = gpa,
4090 .arena = arena,
4091 .source = "true",
4092 .diag = &diag,
4093 }),
4234 );4094 );
4235 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});4095 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
4236 }4096 }
42374097
4238 {4098 {
4239 var diag: Diagnostics = .{};4099 var diag: Diagnostics = .init(arena);
4240 defer diag.deinit(gpa);
4241 try std.testing.expectError(4100 try std.testing.expectError(
4242 error.ParseZon,4101 error.ParseZon,
4243 fromSliceAlloc(*const ?*const enum { foo }, .{ .gpa = gpa, .source = "true", .diag = &diag }),4102 fromSliceAlloc(*const ?*const enum { foo }, .{
4103 .gpa = gpa,
4104 .arena = arena,
4105 .source = "true",
4106 .diag = &diag,
4107 }),
4244 );4108 );
4245 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});4109 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
4246 }4110 }
...@@ -4255,26 +4119,35 @@ test "std.zon stop on node" {...@@ -4255,26 +4119,35 @@ test "std.zon stop on node" {
4255 y: f32,4119 y: f32,
4256 };4120 };
42574121
4258 var diag: Diagnostics = .{};4122 var ast = try std.zig.Ast.parse(gpa, ".{ .x = 1.5, .y = 2.5 }", .{ .mode = .zon });
4259 defer diag.deinit(gpa);4123 defer ast.deinit(gpa);
4260 const result = try fromSlice(Vec2, .{4124
4261 .gpa = gpa,4125 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
4262 .source = ".{ .x = 1.5, .y = 2.5 }",4126 defer zoir.deinit(gpa);
4263 .diag = &diag,4127
4128 const result = try fromZoir(Vec2, .{
4129 .ast = &ast,
4130 .zoir = &zoir,
4131 .diag = null,
4264 });4132 });
4133
4265 try std.testing.expectEqual(result.y, 2.5);4134 try std.testing.expectEqual(result.y, 2.5);
4266 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.5 }, result.x.get(diag.zoir));4135 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.5 }, result.x.get(&zoir));
4267 }4136 }
42684137
4269 {4138 {
4270 var diag: Diagnostics = .{};4139 var ast = try std.zig.Ast.parse(gpa, "1.23", .{ .mode = .zon });
4271 defer diag.deinit(gpa);4140 defer ast.deinit(gpa);
4272 const result = try fromSlice(Zoir.Node.Index, .{4141
4273 .gpa = gpa,4142 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
4274 .source = "1.23",4143 defer zoir.deinit(gpa);
4275 .diag = &diag,4144
4145 const result = try fromZoir(Zoir.Node.Index, .{
4146 .ast = &ast,
4147 .zoir = &zoir,
4148 .diag = null,
4276 });4149 });
4277 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(diag.zoir));4150 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(&zoir));
4278 }4151 }
4279}4152}
42804153
...@@ -4300,12 +4173,19 @@ test "std.zon no alloc" {...@@ -4300,12 +4173,19 @@ test "std.zon no alloc" {
43004173
4301 try std.testing.expectEqual(4174 try std.testing.expectEqual(
4302 Nested{ 1, 2, .{ 3, 4 } },4175 Nested{ 1, 2, .{ 3, 4 } },
4303 try fromZoir(Nested, .{ .ast = ast, .zoir = zoir, .diag = null }),4176 try fromZoir(Nested, .{
4177 .ast = &ast,
4178 .zoir = &zoir,
4179 .diag = null,
4180 }),
4304 );4181 );
4305}4182}
43064183
4307test "std.zon errors without diagnostics" {4184test "std.zon errors without diagnostics" {
4308 const gpa = std.testing.allocator;4185 const gpa = std.testing.allocator;
4186 var arena_allocator: ArenaAllocator = .init(gpa);
4187 defer arena_allocator.deinit();
4188 const arena = arena_allocator.allocator();
43094189
4310 const Enum = enum {4190 const Enum = enum {
4311 foo,4191 foo,
...@@ -4314,6 +4194,7 @@ test "std.zon errors without diagnostics" {...@@ -4314,6 +4194,7 @@ test "std.zon errors without diagnostics" {
4314 };4194 };
4315 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Enum, .{4195 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Enum, .{
4316 .gpa = gpa,4196 .gpa = gpa,
4197 .arena = arena,
4317 .source = ".nothing",4198 .source = ".nothing",
4318 .diag = null,4199 .diag = null,
4319 }));4200 }));
...@@ -4323,6 +4204,7 @@ test "std.zon errors without diagnostics" {...@@ -4323,6 +4204,7 @@ test "std.zon errors without diagnostics" {
4323 };4204 };
4324 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{4205 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
4325 .gpa = gpa,4206 .gpa = gpa,
4207 .arena = arena,
4326 .source = ".{ .name = \"Alice\", .age = 25 }",4208 .source = ".{ .name = \"Alice\", .age = 25 }",
4327 .diag = null,4209 .diag = null,
4328 }));4210 }));
...@@ -4333,11 +4215,13 @@ test "std.zon errors without diagnostics" {...@@ -4333,11 +4215,13 @@ test "std.zon errors without diagnostics" {
4333 };4215 };
4334 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{4216 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
4335 .gpa = gpa,4217 .gpa = gpa,
4218 .arena = arena,
4336 .source = ".a",4219 .source = ".a",
4337 .diag = null,4220 .diag = null,
4338 }));4221 }));
4339 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{4222 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
4340 .gpa = gpa,4223 .gpa = gpa,
4224 .arena = arena,
4341 .source = ".{ .b = 8 }",4225 .source = ".{ .b = 8 }",
4342 .diag = null,4226 .diag = null,
4343 }));4227 }));
...@@ -4345,6 +4229,9 @@ test "std.zon errors without diagnostics" {...@@ -4345,6 +4229,9 @@ test "std.zon errors without diagnostics" {
43454229
4346test "std.zon aligned pointers" {4230test "std.zon aligned pointers" {
4347 const gpa = std.testing.allocator;4231 const gpa = std.testing.allocator;
4232 var arena_allocator: ArenaAllocator = .init(gpa);
4233 defer arena_allocator.deinit();
4234 const arena = arena_allocator.allocator();
43484235
4349 const n: u8 align(8) = 10;4236 const n: u8 align(8) = 10;
4350 const Foo = struct {4237 const Foo = struct {
...@@ -4356,15 +4243,18 @@ test "std.zon aligned pointers" {...@@ -4356,15 +4243,18 @@ test "std.zon aligned pointers" {
4356 };4243 };
4357 const found = try fromSliceAlloc(Foo, .{4244 const found = try fromSliceAlloc(Foo, .{
4358 .gpa = gpa,4245 .gpa = gpa,
4246 .arena = arena,
4359 .source = ".{ .inner = 10 }",4247 .source = ".{ .inner = 10 }",
4360 .diag = null,4248 .diag = null,
4361 });4249 });
4362 defer free(gpa, found);
4363 try std.testing.expectEqualDeep(expected.inner, found.inner);4250 try std.testing.expectEqualDeep(expected.inner, found.inner);
4364}4251}
43654252
4366test "std.zon update" {4253test "std.zon update" {
4367 const gpa = std.testing.allocator;4254 const gpa = std.testing.allocator;
4255 var arena_allocator: ArenaAllocator = .init(gpa);
4256 defer arena_allocator.deinit();
4257 const arena = arena_allocator.allocator();
43684258
4369 const Vector = struct { x: f32, y: f32, z: f32 };4259 const Vector = struct { x: f32, y: f32, z: f32 };
4370 const MyStruct = struct {4260 const MyStruct = struct {
...@@ -4379,51 +4269,43 @@ test "std.zon update" {...@@ -4379,51 +4269,43 @@ test "std.zon update" {
4379 str: []const u8,4269 str: []const u8,
4380 };4270 };
43814271
4272 var v1: Vector = .{ .x = 1, .y = 2, .z = 3 };
4382 var expected: MyStruct = .{4273 var expected: MyStruct = .{
4383 .foo = 10,4274 .foo = 10,
4384 .bar = true,4275 .bar = true,
4385 .baz = .{ .a = .{ 1, 2 }, .b = .c },4276 .baz = .{ .a = .{ 1, 2 }, .b = .c },
4386 .ptr = b: {4277 .ptr = &v1,
4387 const v = gpa.create(Vector) catch @panic("oom");4278 .str = "hello, world",
4388 v.* = .{ .x = 1, .y = 2, .z = 3 };
4389 break :b v;
4390 },
4391 .str = gpa.dupe(u8, "hello, world") catch @panic("oom"),
4392 };4279 };
4393 defer free(gpa, expected);4280 var v2: Vector = .{ .x = 1, .y = 2, .z = 3 };
4394 var found: MyStruct = .{4281 var found: MyStruct = .{
4395 .foo = 10,4282 .foo = 10,
4396 .bar = true,4283 .bar = true,
4397 .baz = .{ .a = .{ 1, 2 }, .b = .c },4284 .baz = .{ .a = .{ 1, 2 }, .b = .c },
4398 .ptr = b: {4285 .ptr = &v2,
4399 const v = gpa.create(Vector) catch @panic("oom");4286 .str = "hello, world",
4400 v.* = .{ .x = 1, .y = 2, .z = 3 };
4401 break :b v;
4402 },
4403 .str = gpa.dupe(u8, "hello, world") catch @panic("oom"),
4404 };4287 };
4405 defer free(gpa, found);
44064288
4407 try updateFromSliceAlloc(MyStruct, .{4289 try updateFromSliceAlloc(MyStruct, &found, .{
4408 .gpa = gpa,4290 .gpa = gpa,
4409 .value = &found,4291 .arena = arena,
4410 .source = ".{}",4292 .source = ".{}",
4411 .diag = null,4293 .diag = null,
4412 });4294 });
4413 try std.testing.expectEqualDeep(expected, found);4295 try std.testing.expectEqualDeep(expected, found);
44144296
4415 try updateFromSliceAlloc(MyStruct, .{4297 try updateFromSliceAlloc(MyStruct, &found, .{
4416 .gpa = gpa,4298 .gpa = gpa,
4417 .value = &found,4299 .arena = arena,
4418 .source = ".{ .bar = false }",4300 .source = ".{ .bar = false }",
4419 .diag = null,4301 .diag = null,
4420 });4302 });
4421 expected.bar = false;4303 expected.bar = false;
4422 try std.testing.expectEqualDeep(expected, found);4304 try std.testing.expectEqualDeep(expected, found);
44234305
4424 try updateFromSliceAlloc(MyStruct, .{4306 try updateFromSliceAlloc(MyStruct, &found, .{
4425 .gpa = gpa,4307 .gpa = gpa,
4426 .value = &found,4308 .arena = arena,
4427 .source = ".{ .baz = .{ .a = .{ 2, 4 } } }",4309 .source = ".{ .baz = .{ .a = .{ 2, 4 } } }",
4428 .diag = null,4310 .diag = null,
4429 });4311 });
...@@ -4431,9 +4313,9 @@ test "std.zon update" {...@@ -4431,9 +4313,9 @@ test "std.zon update" {
4431 expected.baz.a[1] = 4;4313 expected.baz.a[1] = 4;
4432 try std.testing.expectEqualDeep(expected, found);4314 try std.testing.expectEqualDeep(expected, found);
44334315
4434 try updateFromSliceAlloc(MyStruct, .{4316 try updateFromSliceAlloc(MyStruct, &found, .{
4435 .gpa = gpa,4317 .gpa = gpa,
4436 .value = &found,4318 .arena = arena,
4437 .source = ".{ .foo = 11, .baz = .{ .b = .d } }",4319 .source = ".{ .foo = 11, .baz = .{ .b = .d } }",
4438 .diag = null,4320 .diag = null,
4439 });4321 });
...@@ -4441,27 +4323,27 @@ test "std.zon update" {...@@ -4441,27 +4323,27 @@ test "std.zon update" {
4441 expected.baz.b = .d;4323 expected.baz.b = .d;
4442 try std.testing.expectEqualDeep(expected, found);4324 try std.testing.expectEqualDeep(expected, found);
44434325
4444 try updateFromSliceAlloc(MyStruct, .{4326 try updateFromSliceAlloc(MyStruct, &found, .{
4445 .gpa = gpa,4327 .gpa = gpa,
4446 .value = &found,4328 .arena = arena,
4447 .source = ".{ .optional = 10 }",4329 .source = ".{ .optional = 10 }",
4448 .diag = null,4330 .diag = null,
4449 });4331 });
4450 expected.optional = 10;4332 expected.optional = 10;
4451 try std.testing.expectEqualDeep(expected, found);4333 try std.testing.expectEqualDeep(expected, found);
44524334
4453 try updateFromSliceAlloc(MyStruct, .{4335 try updateFromSliceAlloc(MyStruct, &found, .{
4454 .gpa = gpa,4336 .gpa = gpa,
4455 .value = &found,4337 .arena = arena,
4456 .source = ".{ .optional = null }",4338 .source = ".{ .optional = null }",
4457 .diag = null,4339 .diag = null,
4458 });4340 });
4459 expected.optional = null;4341 expected.optional = null;
4460 try std.testing.expectEqualDeep(expected, found);4342 try std.testing.expectEqualDeep(expected, found);
44614343
4462 try updateFromSliceAlloc(MyStruct, .{4344 try updateFromSliceAlloc(MyStruct, &found, .{
4463 .gpa = gpa,4345 .gpa = gpa,
4464 .value = &found,4346 .arena = arena,
4465 .source = ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",4347 .source = ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",
4466 .diag = null,4348 .diag = null,
4467 });4349 });
...@@ -4470,14 +4352,13 @@ test "std.zon update" {...@@ -4470,14 +4352,13 @@ test "std.zon update" {
4470 expected.ptr.z = 30;4352 expected.ptr.z = 30;
4471 try std.testing.expectEqualDeep(expected, found);4353 try std.testing.expectEqualDeep(expected, found);
44724354
4473 try updateFromSliceAlloc(MyStruct, .{4355 try updateFromSliceAlloc(MyStruct, &found, .{
4474 .gpa = gpa,4356 .gpa = gpa,
4475 .value = &found,4357 .arena = arena,
4476 .source = ".{ .str = \"foo\" }",4358 .source = ".{ .str = \"foo\" }",
4477 .diag = null,4359 .diag = null,
4478 });4360 });
4479 gpa.free(expected.str);4361 expected.str = "foo";
4480 expected.str = gpa.dupe(u8, "foo") catch @panic("oom");
4481 try std.testing.expectEqualDeep(expected, found);4362 try std.testing.expectEqualDeep(expected, found);
4482}4363}
44834364
...@@ -4486,6 +4367,9 @@ test "std.zon variants" {...@@ -4486,6 +4367,9 @@ test "std.zon variants" {
4486 // the same code.4367 // the same code.
44874368
4488 const gpa = std.testing.allocator;4369 const gpa = std.testing.allocator;
4370 var arena_allocator: ArenaAllocator = .init(gpa);
4371 defer arena_allocator.deinit();
4372 const arena = arena_allocator.allocator();
44894373
4490 const Struct = struct { a: u32, b: u32 };4374 const Struct = struct { a: u32, b: u32 };
4491 const start: Struct = .{ .a = 10, .b = 20 };4375 const start: Struct = .{ .a = 10, .b = 20 };
...@@ -4499,38 +4383,35 @@ test "std.zon variants" {...@@ -4499,38 +4383,35 @@ test "std.zon variants" {
4499 defer zoir.deinit(gpa);4383 defer zoir.deinit(gpa);
45004384
4501 var curr = start;4385 var curr = start;
4502 try updateFromSlice(Struct, .{4386 try updateFromSlice(Struct, &curr, .{
4503 .gpa = gpa,4387 .gpa = gpa,
4504 .value = &curr,
4505 .source = ".{ .a = 100 }",4388 .source = ".{ .a = 100 }",
4506 .diag = null,4389 .diag = null,
4507 });4390 });
4508 try std.testing.expectEqual(end, curr);4391 try std.testing.expectEqual(end, curr);
45094392
4510 curr = start;4393 curr = start;
4511 try updateFromSliceAlloc(Struct, .{4394 try updateFromSliceAlloc(Struct, &curr, .{
4512 .gpa = gpa,4395 .gpa = gpa,
4513 .value = &curr,4396 .arena = arena,
4514 .source = ".{ .a = 100 }",4397 .source = ".{ .a = 100 }",
4515 .diag = null,4398 .diag = null,
4516 });4399 });
4517 try std.testing.expectEqual(end, curr);4400 try std.testing.expectEqual(end, curr);
45184401
4519 curr = start;4402 curr = start;
4520 try updateFromZoir(Struct, .{4403 try updateFromZoir(Struct, &curr, .{
4521 .ast = ast,4404 .ast = &ast,
4522 .value = &curr,4405 .zoir = &zoir,
4523 .zoir = zoir,
4524 .diag = null,4406 .diag = null,
4525 });4407 });
4526 try std.testing.expectEqual(end, curr);4408 try std.testing.expectEqual(end, curr);
45274409
4528 curr = start;4410 curr = start;
4529 try updateFromZoirAlloc(Struct, .{4411 try updateFromZoirAlloc(Struct, &curr, .{
4530 .gpa = gpa,4412 .arena = arena,
4531 .value = &curr,4413 .ast = &ast,
4532 .ast = ast,4414 .zoir = &zoir,
4533 .zoir = zoir,
4534 .diag = null,4415 .diag = null,
4535 });4416 });
4536 try std.testing.expectEqual(end, curr);4417 try std.testing.expectEqual(end, curr);
...@@ -4555,23 +4436,24 @@ test "std.zon variants" {...@@ -4555,23 +4436,24 @@ test "std.zon variants" {
4555 end,4436 end,
4556 try fromSliceAlloc(Struct, .{4437 try fromSliceAlloc(Struct, .{
4557 .gpa = gpa,4438 .gpa = gpa,
4439 .arena = arena,
4558 .source = ".{ .a = 100, .b = 20 }",4440 .source = ".{ .a = 100, .b = 20 }",
4559 .diag = null,4441 .diag = null,
4560 }),4442 }),
4561 );4443 );
4562 try std.testing.expectEqual(4444 try std.testing.expectEqual(
4563 try fromZoir(Struct, .{4445 try fromZoir(Struct, .{
4564 .ast = ast,4446 .ast = &ast,
4565 .zoir = zoir,4447 .zoir = &zoir,
4566 .diag = null,4448 .diag = null,
4567 }),4449 }),
4568 end,4450 end,
4569 );4451 );
4570 try std.testing.expectEqual(4452 try std.testing.expectEqual(
4571 try fromZoirAlloc(Struct, .{4453 try fromZoirAlloc(Struct, .{
4572 .gpa = gpa,4454 .arena = arena,
4573 .ast = ast,4455 .ast = &ast,
4574 .zoir = zoir,4456 .zoir = &zoir,
4575 .diag = null,4457 .diag = null,
4576 }),4458 }),
4577 end,4459 end,