authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-08-07 17:50:51-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-09-26 12:35:38-07:00
loga6552e7d009883ae33a1b6aa24d216df6c964f17
tree9ac1a677dce56ed356f02e0f9f14f59341e26299
parente4a7988fec0d53e5f48a1701aeebacf192198203

Cleans up memory management and error reporting

- Use the same arena for errors and results - Store errors as a slice rather than an array list - Make the errors container non-optional - Rename functions like `fromSliceAlloc`/`fromSlice` to `fromSlice`/`fromSliceNoAlloc` - Cleans up error formatting and internal helper structure

1 files changed, 1012 insertions(+), 852 deletions(-)

lib/std/zon/parse.zig+1012-852
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1//! Use `fromSlice`/`fromSliceAlloc` to parse a ZON string into a Zig value. Human readable errors1//! Use `fromSlice`/`fromSlice` to parse a ZON string into a Zig value. Human readable errors
2//! are written to an out parameter.2//! are written to an out parameter.
3//!3//!
4//! If your data is already available in tree form, consider `fromZoir`/`fromZoirAlloc`.4//! If your data is already available in tree form, consider `fromZoir`/`fromZoir`.
5//!5//!
6//! To parse into an existing value, see the `updateFrom*` variants. For lower level control over6//! To parse into an existing value, see the `updateFrom*` variants. For lower level control over
7//! parsing, see `std.zig.ZonGen`. For importing ZON at compile time, use `@import`.7//! parsing, see `std.zig.ZonGen`. For importing ZON at compile time, use `@import`.
...@@ -93,15 +93,9 @@ pub const Error = struct {...@@ -93,15 +93,9 @@ pub const Error = struct {
9393
94/// Errors encountered while parsing ZON. See `log` and `fatal` for reporting errors to the user.94/// Errors encountered while parsing ZON. See `log` and `fatal` for reporting errors to the user.
95pub const Errors = struct {95pub const Errors = struct {
96 arena: Allocator,96 items: []const Error,
97 list: std.ArrayList(Error),
9897
99 pub fn init(arena: Allocator) Errors {98 pub const empty: Errors = .{ .items = &.{} };
100 return .{
101 .arena = arena,
102 .list = .empty,
103 };
104 }
10599
106 /// Log the failure with `std.log.err`.100 /// Log the failure with `std.log.err`.
107 pub fn log(101 pub fn log(
...@@ -109,7 +103,7 @@ pub const Errors = struct {...@@ -109,7 +103,7 @@ pub const Errors = struct {
109 path: []const u8,103 path: []const u8,
110 err: error{ OutOfMemory, ParseZon },104 err: error{ OutOfMemory, ParseZon },
111 ) void {105 ) void {
112 std.log.err("{s}: {}\n{f}", .{ path, err, self.fmt(path) });106 std.log.err("{f}", .{self.fmt(path, err)});
113 }107 }
114108
115 test log {109 test log {
...@@ -117,17 +111,18 @@ pub const Errors = struct {...@@ -117,17 +111,18 @@ pub const Errors = struct {
117 var arena_allocator: ArenaAllocator = .init(gpa);111 var arena_allocator: ArenaAllocator = .init(gpa);
118 defer arena_allocator.deinit();112 defer arena_allocator.deinit();
119 const arena = arena_allocator.allocator();113 const arena = arena_allocator.allocator();
114 var errors: Errors = .empty;
120115
121 const MyType = struct {116 const MyType = struct {
122 foo: u32,117 foo: u32,
123 bar: u32,118 bar: u32,
124 };119 };
125120
126 const errors: Errors = .init(arena);121 const parsed: MyType = fromSliceNoAlloc(MyType, .{
127 const parsed: MyType = fromSlice(MyType, .{
128 .gpa = gpa,122 .gpa = gpa,
123 .arena = arena,
129 .source = ".{ .foo = 1, .bar = 2 }",124 .source = ".{ .foo = 1, .bar = 2 }",
130 .errors = null,125 .errors = &errors,
131 }) catch |err| b: {126 }) catch |err| b: {
132 errors.log("input.zon", err);127 errors.log("input.zon", err);
133 break :b .{ .foo = 0, .bar = 0 };128 break :b .{ .foo = 0, .bar = 0 };
...@@ -141,7 +136,7 @@ pub const Errors = struct {...@@ -141,7 +136,7 @@ pub const Errors = struct {
141 path: []const u8,136 path: []const u8,
142 err: error{ OutOfMemory, ParseZon },137 err: error{ OutOfMemory, ParseZon },
143 ) noreturn {138 ) noreturn {
144 std.process.fatal("{s}: {}\n{f}", .{ path, err, self.fmt(path) });139 std.process.fatal("{f}", .{self.fmt(path, err)});
145 }140 }
146141
147 test fatal {142 test fatal {
...@@ -149,34 +144,42 @@ pub const Errors = struct {...@@ -149,34 +144,42 @@ pub const Errors = struct {
149 var arena_allocator: ArenaAllocator = .init(gpa);144 var arena_allocator: ArenaAllocator = .init(gpa);
150 defer arena_allocator.deinit();145 defer arena_allocator.deinit();
151 const arena = arena_allocator.allocator();146 const arena = arena_allocator.allocator();
147 var errors: Errors = .empty;
152148
153 const MyType = struct {149 const MyType = struct {
154 foo: u32,150 foo: u32,
155 bar: u32,151 bar: u32,
156 };152 };
157153
158 const errors: Errors = .init(arena);154 const parsed = fromSliceNoAlloc(MyType, .{
159 const parsed = fromSlice(MyType, .{
160 .gpa = gpa,155 .gpa = gpa,
156 .arena = arena,
161 .source = ".{ .foo = 1, .bar = 2 }",157 .source = ".{ .foo = 1, .bar = 2 }",
162 .errors = null,158 .errors = &errors,
163 }) catch |err| errors.fatal("input.zon", err);159 }) catch |err| errors.fatal("input.zon", err);
164 _ = parsed;160 _ = parsed;
165 }161 }
166162
167 pub fn fmt(self: *const Errors, path: []const u8) Formatter {163 pub fn fmt(
164 self: *const Errors,
165 path: []const u8,
166 err: error{ OutOfMemory, ParseZon },
167 ) Formatter {
168 return .{168 return .{
169 .items = self.items,
169 .path = path,170 .path = path,
170 .errors = self.list.items,171 .err = err,
171 };172 };
172 }173 }
173174
174 pub const Formatter = struct {175 pub const Formatter = struct {
175 path: []const u8,176 path: []const u8,
176 errors: []const Error,177 items: []const Error,
178 err: error{ OutOfMemory, ParseZon },
177179
178 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {180 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
179 for (self.errors) |e| {181 try w.print("{s}: {}\n", .{ self.path, self.err });
182 for (self.items) |e| {
180 try w.print("{s}:", .{self.path});183 try w.print("{s}:", .{self.path});
181 try w.print("{d}:{d}: error: {s}\n", .{184 try w.print("{d}:{d}: error: {s}\n", .{
182 e.loc.line + 1,185 e.loc.line + 1,
...@@ -200,263 +203,181 @@ pub const Errors = struct {...@@ -200,263 +203,181 @@ pub const Errors = struct {
200pub const FromSliceOptions = struct {203pub const FromSliceOptions = struct {
201 /// Used for scratch allocations.204 /// Used for scratch allocations.
202 gpa: Allocator,205 gpa: Allocator,
206 /// Used for allocating errors and results.
207 arena: Allocator,
203 /// The ZON source to parse.208 /// The ZON source to parse.
204 source: [:0]const u8,209 source: [:0]const u8,
205 /// If non-null, any errors encountered are appended here.210 /// When an error is returned from the parser, a human readable error description of the failure
206 errors: ?*Errors,211 /// is stored here.
212 errors: *Errors,
207 /// If true, unknown fields do not error.213 /// If true, unknown fields do not error.
208 ignore_unknown_fields: bool = false,214 ignore_unknown_fields: bool = false,
209};215};
210216
211/// Parses the given slice as ZON.217/// Parses the given slice as ZON.
212///218///
213/// Returns `error.OutOfMemory` on allocation failure, or `error.ParseZon` error if the ZON is219/// Human readable errors are written to `options.errors`. `options.arena` owns the errors, and any
214/// invalid or can not be deserialized into type `T`.220/// pointers that are part of `T`.
215///
216/// When the parser returns `error.ParseZon`, it will also store a human readable explanation in
217/// `errors` if non null.
218///
219/// Asserts at compile time that the result type doesn't contain pointers. As such, the result
220/// doesn't need to be freed.
221///
222/// An allocator is still required for temporary allocations made during parsing.
223pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {221pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
222 var value: T = undefined;
223 try fromSliceInner(T, &value, false, options);
224 return value;
225}
226
227/// Like `fromSlice` but the result type may not contain pointers, allowing it to outlive
228/// `options.arena`.
229pub fn fromSliceNoAlloc(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
224 comptime assert(!requiresAllocator(T));230 comptime assert(!requiresAllocator(T));
225 return fromSliceAlloc(T, .{231 return fromSlice(T, options);
226 .gpa = options.gpa,
227 .arena = .failing,
228 .source = options.source,
229 .errors = options.errors,
230 .ignore_unknown_fields = options.ignore_unknown_fields,
231 });
232}232}
233233
234/// Similar to `fromSlice`, but updates `value` in place which is assumed to hold a valid value. Any234/// Similar to `fromSlice`, but updates `value` in place. `value` must be initialized before this
235/// unspecified fields are left unchanged.235/// call, fields not specified in ZON are left unchanged.
236///236///
237/// Untagged unions and slices are replaced in their entiredy. If an error occurs while parsing,237/// Whenever a slice or an untagged union is specified, it completely overwites the previous value.
238/// `value` remains valid but may be partially updated.238/// On error, `value` remains valid, but may be partially updated.
239pub fn updateFromSlice(239pub fn updateFromSlice(
240 T: type,240 T: type,
241 value: *T,241 value: *T,
242 options: FromSliceOptions,242 options: FromSliceOptions,
243) error{ OutOfMemory, ParseZon }!void {243) error{ OutOfMemory, ParseZon }!void {
244 comptime assert(!requiresAllocator(T));244 try fromSliceInner(T, value, true, options);
245 try updateFromSliceAlloc(T, value, .{
246 .gpa = options.gpa,
247 .arena = .failing,
248 .source = options.source,
249 .errors = options.errors,
250 .ignore_unknown_fields = options.ignore_unknown_fields,
251 });
252}
253
254pub const FromSliceAllocOptions = struct {
255 /// Used for scratch allocations.
256 gpa: Allocator,
257 /// Used for any allocations required by the out type.
258 arena: Allocator,
259 /// The ZON source to parse.
260 source: [:0]const u8,
261 /// If non-null, any errors encountered are appended here.
262 errors: ?*Errors,
263 /// If true, unknown fields do not error.
264 ignore_unknown_fields: bool = false,
265};
266
267/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see
268/// `free`.
269pub fn fromSliceAlloc(T: type, options: FromSliceAllocOptions) error{ OutOfMemory, ParseZon }!T {
270 var value: T = undefined;
271 try parseSliceAlloc(T, &value, .{
272 .gpa = options.gpa,
273 .arena = options.arena,
274 .source = options.source,
275 .errors = options.errors,
276 .ignore_unknown_fields = options.ignore_unknown_fields,
277 .initialized = false,
278 });
279 return value;
280}245}
281246
282/// Like updateFromSlice`, but the result may contain pointers.247/// Like `updateFromSlice` but the `T` may not contain pointers, allowing `value` to outlive
283pub fn updateFromSliceAlloc(248/// `options.arena`.
249pub fn updateFromSliceNoAlloc(
284 T: type,250 T: type,
285 value: *T,251 value: *T,
286 options: FromSliceAllocOptions,252 options: FromSliceOptions,
287) error{ OutOfMemory, ParseZon }!void {253) error{ OutOfMemory, ParseZon }!void {
288 try parseSliceAlloc(T, value, .{254 comptime assert(!requiresAllocator(T));
289 .gpa = options.gpa,255 try fromSliceInner(T, value, true, options);
290 .arena = options.arena,
291 .source = options.source,
292 .errors = options.errors,
293 .ignore_unknown_fields = options.ignore_unknown_fields,
294 .initialized = true,
295 });
296}256}
297257
298const ParseSliceAllocOptions = struct {258fn fromSliceInner(
299 gpa: Allocator,
300 arena: Allocator,
301 source: [:0]const u8,
302 errors: ?*Errors,
303 ignore_unknown_fields: bool,
304 initialized: bool,
305};
306
307fn parseSliceAlloc(
308 T: type,259 T: type,
309 value: *T,260 value: *T,
310 options: ParseSliceAllocOptions,261 initialized: bool,
262 options: FromSliceOptions,
311) error{ OutOfMemory, ParseZon }!void {263) error{ OutOfMemory, ParseZon }!void {
264 var errors: std.ArrayList(Error) = .empty;
265 defer options.errors.items = errors.items;
266
312 var ast = try std.zig.Ast.parse(options.gpa, options.source, .{ .mode = .zon });267 var ast = try std.zig.Ast.parse(options.gpa, options.source, .{ .mode = .zon });
313 defer ast.deinit(options.gpa);268 defer ast.deinit(options.gpa);
314269
315 var zoir = try ZonGen.generate(options.gpa, ast, .{ .parse_str_lits = false });270 var zoir = try ZonGen.generate(options.gpa, ast, .{ .parse_str_lits = false });
316 defer zoir.deinit(options.gpa);271 defer zoir.deinit(options.gpa);
317272
318 try parseZoirAlloc(T, value, .{273 try inner(T, value, initialized, .{
319 .arena = options.arena,274 .arena = options.arena,
320 .ast = &ast,275 .ast = &ast,
321 .zoir = &zoir,276 .zoir = &zoir,
322 .node = .root,277 .node = .root,
323 .errors = options.errors,278 .errors = &errors,
324 .ignore_unknown_fields = options.ignore_unknown_fields,279 .ignore_unknown_fields = options.ignore_unknown_fields,
325 .initialized = options.initialized,
326 });280 });
327}281}
328282
329pub const FromZoirOptions = struct {283pub const FromZoirOptions = struct {
330 /// The AST for this this ZON value.284 /// Used for allocating errors and results.
285 arena: Allocator,
286 /// The AST for this ZON value.
331 ast: *const Ast,287 ast: *const Ast,
332 /// The zig object intermediate representation of this ZON value.288 /// The zig object intermediate representation of this ZON value.
333 zoir: *const Zoir,289 zoir: *const Zoir,
334 /// The node to start parsing at.290 /// The node to start parsing at.
335 node: Zoir.Node.Index = .root,291 node: Zoir.Node.Index = .root,
336 /// If non-null, any errors encountered are appended here.292 /// When an error is returned from the parser, a human readable error description of the failure
337 errors: ?*Errors,293 /// is stored here.
294 errors: *Errors,
338 /// If true, unknown fields do not error.295 /// If true, unknown fields do not error.
339 ignore_unknown_fields: bool = false,296 ignore_unknown_fields: bool = false,
340};297};
341298
342/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.299/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
343pub fn fromZoir(T: type, options: FromZoirOptions) error{ParseZon}!T {300pub fn fromZoir(T: type, options: FromZoirOptions) error{ OutOfMemory, ParseZon }!T {
301 var value: T = undefined;
302 try fromZoirInner(T, &value, false, options);
303 return value;
304}
305
306/// Like `fromSliceNoAlloc`, but operates on `Zoir` instead of ZON source.
307pub fn fromZoirNoAlloc(T: type, options: FromZoirOptions) error{ OutOfMemory, ParseZon }!T {
344 comptime assert(!requiresAllocator(T));308 comptime assert(!requiresAllocator(T));
345 return fromZoirAlloc(T, .{309 return fromZoir(T, options);
346 .arena = .failing,
347 .ast = options.ast,
348 .zoir = options.zoir,
349 .node = options.node,
350 .errors = options.errors,
351 .ignore_unknown_fields = options.ignore_unknown_fields,
352 }) catch |err| switch (err) {
353 error.OutOfMemory => unreachable, // Checked by comptime assertion above
354 else => |e| return e,
355 };
356}310}
357311
358/// Like `updateSlice`, but operates on `Zoir` instead of ZON source.312/// Like `updateFromSlice`, but operates on `Zoir` instead of ZON source.
359pub fn updateFromZoir(313pub fn updateFromZoir(
360 T: type,314 T: type,
361 value: *T,315 value: *T,
362 options: FromZoirOptions,316 options: FromZoirOptions,
363) error{ParseZon}!void {317) error{ OutOfMemory, ParseZon }!void {
364 comptime assert(!requiresAllocator(T));318 return fromZoirInner(T, value, true, options);
365 updateFromZoirAlloc(T, value, .{
366 .arena = .failing,
367 .ast = options.ast,
368 .zoir = options.zoir,
369 .node = options.node,
370 .errors = options.errors,
371 .ignore_unknown_fields = options.ignore_unknown_fields,
372 }) catch |err| switch (err) {
373 error.OutOfMemory => unreachable, // Checked by comptime assertion above
374 else => |e| return e,
375 };
376}319}
377320
378pub const FromZoirAllocOptions = struct {321/// Like `updateFromSliceNoAlloc`, but operates on `Zoir` instead of ZON source.
379 /// Used for any allocations required by the out type.322pub fn updateFromZoirNoAlloc(
380 arena: Allocator,323 T: type,
381 /// The AST for this ZON value.324 value: *T,
382 ast: *const Ast,325 options: FromZoirOptions,
383 /// The zig object intermediate representation of this ZON value.326) error{ OutOfMemory, ParseZon }!void {
384 zoir: *const Zoir,327 comptime assert(!requiresAllocator(T));
385 /// The node to start parsing at.328 return updateFromZoir(T, value, options);
386 node: Zoir.Node.Index = .root,
387 /// If non-null, any errors encountered are appended here.
388 errors: ?*Errors,
389 /// If true, unknown fields do not error.
390 ignore_unknown_fields: bool = false,
391};
392
393/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
394pub fn fromZoirAlloc(T: type, options: FromZoirAllocOptions) error{ OutOfMemory, ParseZon }!T {
395 var value: T = undefined;
396 try parseZoirAlloc(T, &value, .{
397 .arena = options.arena,
398 .ast = options.ast,
399 .zoir = options.zoir,
400 .node = options.node,
401 .errors = options.errors,
402 .ignore_unknown_fields = options.ignore_unknown_fields,
403 .initialized = false,
404 });
405 return value;
406}329}
407330
408/// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source.331fn fromZoirInner(
409pub fn updateFromZoirAlloc(
410 T: type,332 T: type,
411 value: *T,333 value: *T,
412 options: FromZoirAllocOptions,334 initialized: bool,
335 options: FromZoirOptions,
413) error{ OutOfMemory, ParseZon }!void {336) error{ OutOfMemory, ParseZon }!void {
414 return parseZoirAlloc(T, value, .{337 var errors: std.ArrayList(Error) = .empty;
338 defer options.errors.items = errors.items;
339 return inner(T, value, initialized, .{
415 .arena = options.arena,340 .arena = options.arena,
416 .ast = options.ast,341 .ast = options.ast,
417 .zoir = options.zoir,342 .zoir = options.zoir,
418 .node = options.node,343 .errors = &errors,
419 .errors = options.errors,
420 .ignore_unknown_fields = options.ignore_unknown_fields,344 .ignore_unknown_fields = options.ignore_unknown_fields,
421 .initialized = true,
422 });345 });
423}346}
424347
425const ParseZoirAllocOptions = struct {348const InnerOptions = struct {
426 arena: Allocator,349 arena: Allocator,
427 ast: *const Ast,350 ast: *const Ast,
428 zoir: *const Zoir,351 zoir: *const Zoir,
429 node: Zoir.Node.Index,352 node: Zoir.Node.Index = .root,
430 errors: ?*Errors,353 errors: *std.ArrayList(Error),
431 ignore_unknown_fields: bool,354 ignore_unknown_fields: bool,
432 initialized: bool,
433};355};
434356
435fn parseZoirAlloc(357fn inner(
436 T: type,358 T: type,
437 value: *T,359 value: *T,
438 options: ParseZoirAllocOptions,360 initialized: bool,
361 options: InnerOptions,
439) error{ OutOfMemory, ParseZon }!void {362) error{ OutOfMemory, ParseZon }!void {
440 comptime assert(canParseType(T));363 comptime assert(canParseType(T));
441364
442 if (options.zoir.hasCompileErrors()) {365 if (options.zoir.hasCompileErrors()) {
443 if (options.errors) |errors| {366 for (options.zoir.compile_errors) |e| {
444 for (options.zoir.compile_errors) |e| {367 var notes: std.ArrayList(Error.Note) = .empty;
445 var notes: std.ArrayList(Error.Note) = .empty;368 for (e.getNotes(options.zoir)) |note| {
446 for (e.getNotes(options.zoir)) |note| {369 try notes.append(options.arena, .init(options.ast, .{
447 try notes.append(errors.arena, .init(options.ast, .{370 .msg = try options.arena.dupe(u8, note.msg.get(options.zoir)),
448 .msg = try errors.arena.dupe(u8, note.msg.get(options.zoir)),371 .token = note.token,
449 .token = note.token,372 .node_or_offset = note.node_or_offset,
450 .node_or_offset = note.node_or_offset,
451 }));
452 }
453 try errors.list.append(errors.arena, .init(options.ast, .{
454 .msg = try errors.arena.dupe(u8, e.msg.get(options.zoir)),
455 .token = e.token,
456 .node_or_offset = e.node_or_offset,
457 .notes = try notes.toOwnedSlice(errors.arena),
458 }));373 }));
459 }374 }
375 try options.errors.append(options.arena, .init(options.ast, .{
376 .msg = try options.arena.dupe(u8, e.msg.get(options.zoir)),
377 .token = e.token,
378 .node_or_offset = e.node_or_offset,
379 .notes = notes.items,
380 }));
460 }381 }
461 return error.ParseZon;382 return error.ParseZon;
462 }383 }
...@@ -469,7 +390,7 @@ fn parseZoirAlloc(...@@ -469,7 +390,7 @@ fn parseZoirAlloc(
469 .errors = options.errors,390 .errors = options.errors,
470 };391 };
471392
472 try parser.parseExprInto(options.node, value, options.initialized);393 try parser.parseExprInto(options.node, value, initialized);
473}394}
474395
475fn requiresAllocator(T: type) bool {396fn requiresAllocator(T: type) bool {
...@@ -497,7 +418,7 @@ const Parser = struct {...@@ -497,7 +418,7 @@ const Parser = struct {
497 arena: Allocator,418 arena: Allocator,
498 ast: *const Ast,419 ast: *const Ast,
499 zoir: *const Zoir,420 zoir: *const Zoir,
500 errors: ?*Errors,421 errors: *std.ArrayList(Error),
501 ignore_unknown_fields: bool,422 ignore_unknown_fields: bool,
502423
503 const ParseExprError = error{ ParseZon, OutOfMemory };424 const ParseExprError = error{ ParseZon, OutOfMemory };
...@@ -508,7 +429,7 @@ const Parser = struct {...@@ -508,7 +429,7 @@ const Parser = struct {
508 out: anytype,429 out: anytype,
509 initialized: bool,430 initialized: bool,
510 ) ParseExprError!void {431 ) ParseExprError!void {
511 return self.parseExprInnerInto(node, out, initialized) catch |err| switch (err) {432 return self.parseExprIntoInner(node, out, initialized) catch |err| switch (err) {
512 error.WrongType => return self.failExpectedType(@TypeOf(out.*), node),433 error.WrongType => return self.failExpectedType(@TypeOf(out.*), node),
513 else => |e| return e,434 else => |e| return e,
514 };435 };
...@@ -516,7 +437,7 @@ const Parser = struct {...@@ -516,7 +437,7 @@ const Parser = struct {
516437
517 const ParseExprInnerError = error{ ParseZon, OutOfMemory, WrongType };438 const ParseExprInnerError = error{ ParseZon, OutOfMemory, WrongType };
518439
519 fn parseExprInnerInto(440 fn parseExprIntoInner(
520 self: *@This(),441 self: *@This(),
521 node: Zoir.Node.Index,442 node: Zoir.Node.Index,
522 out: anytype,443 out: anytype,
...@@ -531,10 +452,10 @@ const Parser = struct {...@@ -531,10 +452,10 @@ const Parser = struct {
531 .optional => |optional| if (node.get(self.zoir) == .null) {452 .optional => |optional| if (node.get(self.zoir) == .null) {
532 out.* = null;453 out.* = null;
533 } else if (initialized and out.* != null) {454 } else if (initialized and out.* != null) {
534 try self.parseExprInnerInto(node, &out.*.?, true);455 try self.parseExprIntoInner(node, &out.*.?, true);
535 } else {456 } else {
536 var some: optional.child = undefined;457 var some: optional.child = undefined;
537 try self.parseExprInnerInto(node, &some, false);458 try self.parseExprIntoInner(node, &some, false);
538 out.* = some;459 out.* = some;
539 },460 },
540 .bool => out.* = try self.parseBool(node),461 .bool => out.* = try self.parseBool(node),
...@@ -556,7 +477,7 @@ const Parser = struct {...@@ -556,7 +477,7 @@ const Parser = struct {
556 if (initialized) new.* = out.*.*;477 if (initialized) new.* = out.*.*;
557 break :b new;478 break :b new;
558 };479 };
559 try self.parseExprInnerInto(480 try self.parseExprIntoInner(
560 node,481 node,
561 new,482 new,
562 initialized,483 initialized,
...@@ -1072,10 +993,10 @@ const Parser = struct {...@@ -1072,10 +993,10 @@ const Parser = struct {
1072 ) error{ OutOfMemory, ParseZon } {993 ) error{ OutOfMemory, ParseZon } {
1073 @branchHint(.cold);994 @branchHint(.cold);
1074 comptime assert(args.len > 0);995 comptime assert(args.len > 0);
1075 if (self.errors) |errors| try errors.list.append(errors.arena, .init(self.ast, .{996 try self.errors.append(self.arena, .init(self.ast, .{
1076 .token = .fromToken(token),997 .token = .fromToken(token),
1077 .node_or_offset = offset,998 .node_or_offset = offset,
1078 .msg = try std.fmt.allocPrint(errors.arena, fmt, args),999 .msg = try std.fmt.allocPrint(self.arena, fmt, args),
1079 .notes = notes,1000 .notes = notes,
1080 }));1001 }));
1081 return error.ParseZon;1002 return error.ParseZon;
...@@ -1097,7 +1018,7 @@ const Parser = struct {...@@ -1097,7 +1018,7 @@ const Parser = struct {
1097 failure: Error,1018 failure: Error,
1098 ) error{ OutOfMemory, ParseZon } {1019 ) error{ OutOfMemory, ParseZon } {
1099 @branchHint(.cold);1020 @branchHint(.cold);
1100 if (self.errors) |errors| try errors.list.append(errors.arena, failure);1021 try self.errors.append(self.arena, failure);
1101 return error.ParseZon;1022 return error.ParseZon;
1102 }1023 }
11031024
...@@ -1134,7 +1055,6 @@ const Parser = struct {...@@ -1134,7 +1055,6 @@ const Parser = struct {
1134 name: []const u8,1055 name: []const u8,
1135 ) error{ OutOfMemory, ParseZon } {1056 ) error{ OutOfMemory, ParseZon } {
1136 @branchHint(.cold);1057 @branchHint(.cold);
1137 const errors = self.errors orelse return error.ParseZon;
1138 const token = if (field) |f| b: {1058 const token = if (field) |f| b: {
1139 var buf: [2]Ast.Node.Index = undefined;1059 var buf: [2]Ast.Node.Index = undefined;
1140 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;1060 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;
...@@ -1145,13 +1065,13 @@ const Parser = struct {...@@ -1145,13 +1065,13 @@ const Parser = struct {
1145 inline .@"struct", .@"union", .@"enum" => |info| {1065 inline .@"struct", .@"union", .@"enum" => |info| {
1146 var notes: std.ArrayList(Error.Note) = .empty;1066 var notes: std.ArrayList(Error.Note) = .empty;
1147 if (info.field_names.len == 0) {1067 if (info.field_names.len == 0) {
1148 try notes.append(errors.arena, .init(self.ast, .{1068 try notes.append(self.arena, .init(self.ast, .{
1149 .token = .fromToken(token),1069 .token = .fromToken(token),
1150 .node_or_offset = 0,1070 .node_or_offset = 0,
1151 .msg = "none expected",1071 .msg = "none expected",
1152 }));1072 }));
1153 } else {1073 } else {
1154 var aw: std.Io.Writer.Allocating = .init(errors.arena);1074 var aw: std.Io.Writer.Allocating = .init(self.arena);
1155 aw.writer.writeAll("supported: ") catch return error.OutOfMemory;1075 aw.writer.writeAll("supported: ") catch return error.OutOfMemory;
1156 inline for (info.field_names, 0..) |field_name, i| {1076 inline for (info.field_names, 0..) |field_name, i| {
1157 if (i != 0) aw.writer.writeAll(", ") catch return error.OutOfMemory;1077 if (i != 0) aw.writer.writeAll(", ") catch return error.OutOfMemory;
...@@ -1160,7 +1080,7 @@ const Parser = struct {...@@ -1160,7 +1080,7 @@ const Parser = struct {
1160 .allow_underscore = true,1080 .allow_underscore = true,
1161 })}) catch return error.OutOfMemory;1081 })}) catch return error.OutOfMemory;
1162 }1082 }
1163 try notes.append(errors.arena, .init(self.ast, .{1083 try notes.append(self.arena, .init(self.ast, .{
1164 .token = .fromToken(token),1084 .token = .fromToken(token),
1165 .node_or_offset = 0,1085 .node_or_offset = 0,
1166 .msg = try aw.toOwnedSlice(),1086 .msg = try aw.toOwnedSlice(),
...@@ -1171,7 +1091,7 @@ const Parser = struct {...@@ -1171,7 +1091,7 @@ const Parser = struct {
1171 0,1091 0,
1172 "unexpected {s} '{s}'",1092 "unexpected {s} '{s}'",
1173 .{ item_kind, name },1093 .{ item_kind, name },
1174 try notes.toOwnedSlice(errors.arena),1094 notes.items,
1175 );1095 );
1176 },1096 },
1177 else => comptime unreachable,1097 else => comptime unreachable,
...@@ -1187,7 +1107,6 @@ const Parser = struct {...@@ -1187,7 +1107,6 @@ const Parser = struct {
1187 field: usize,1107 field: usize,
1188 ) error{ OutOfMemory, ParseZon } {1108 ) error{ OutOfMemory, ParseZon } {
1189 @branchHint(.cold);1109 @branchHint(.cold);
1190 if (self.errors == null) return error.ParseZon;
1191 const ast_node = node.getAstNode(self.zoir);1110 const ast_node = node.getAstNode(self.zoir);
1192 var buf: [2]Ast.Node.Index = undefined;1111 var buf: [2]Ast.Node.Index = undefined;
1193 const token = if (self.ast.fullStructInit(&buf, ast_node)) |struct_init| b: {1112 const token = if (self.ast.fullStructInit(&buf, ast_node)) |struct_init| b: {
...@@ -1368,19 +1287,21 @@ test "std.zon ast errors" {...@@ -1368,19 +1287,21 @@ test "std.zon ast errors" {
1368 var arena_allocator: ArenaAllocator = .init(gpa);1287 var arena_allocator: ArenaAllocator = .init(gpa);
1369 defer arena_allocator.deinit();1288 defer arena_allocator.deinit();
1370 const arena = arena_allocator.allocator();1289 const arena = arena_allocator.allocator();
1371 var errors: Errors = .init(arena);1290 var errors: Errors = .empty;
1372 try std.testing.expectError(1291 try std.testing.expectError(
1373 error.ParseZon,1292 error.ParseZon,
1374 fromSlice(struct {}, .{1293 fromSliceNoAlloc(struct {}, .{
1375 .gpa = gpa,1294 .gpa = gpa,
1295 .arena = arena,
1376 .source = ".{.x = 1 .y = 2}",1296 .source = ".{.x = 1 .y = 2}",
1377 .errors = &errors,1297 .errors = &errors,
1378 }),1298 }),
1379 );1299 );
1380 try std.testing.expectFmt(1300 try std.testing.expectFmt(
1301 \\input.zon: error.ParseZon
1381 \\input.zon:1:13: error: expected ',' after initializer1302 \\input.zon:1:13: error: expected ',' after initializer
1382 \\1303 \\
1383 , "{f}", .{errors.fmt("input.zon")});1304 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1384}1305}
13851306
1386test "std.zon comments" {1307test "std.zon comments" {
...@@ -1388,21 +1309,23 @@ test "std.zon comments" {...@@ -1388,21 +1309,23 @@ test "std.zon comments" {
1388 var arena_allocator: ArenaAllocator = .init(gpa);1309 var arena_allocator: ArenaAllocator = .init(gpa);
1389 defer arena_allocator.deinit();1310 defer arena_allocator.deinit();
1390 const arena = arena_allocator.allocator();1311 const arena = arena_allocator.allocator();
1312 var errors: Errors = .empty;
13911313
1392 try std.testing.expectEqual(@as(u8, 10), fromSlice(u8, .{1314 try std.testing.expectEqual(@as(u8, 10), fromSliceNoAlloc(u8, .{
1393 .gpa = gpa,1315 .gpa = gpa,
1316 .arena = arena,
1394 .source =1317 .source =
1395 \\// comment1318 \\// comment
1396 \\10 // comment1319 \\10 // comment
1397 \\// comment1320 \\// comment
1398 ,1321 ,
1399 .errors = null,1322 .errors = &errors,
1400 }));1323 }));
14011324
1402 {1325 {
1403 var errors: Errors = .init(arena);1326 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
1404 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
1405 .gpa = gpa,1327 .gpa = gpa,
1328 .arena = arena,
1406 .source =1329 .source =
1407 \\//! comment1330 \\//! comment
1408 \\10 // comment1331 \\10 // comment
...@@ -1410,7 +1333,11 @@ test "std.zon comments" {...@@ -1410,7 +1333,11 @@ test "std.zon comments" {
1410 ,1333 ,
1411 .errors = &errors,1334 .errors = &errors,
1412 }));1335 }));
1413 try std.testing.expectFmt("input.zon:1:1: error: expected expression, found 'a document comment'\n", "{f}", .{errors.fmt("input.zon")});1336 try std.testing.expectFmt(
1337 \\input.zon: error.ParseZon
1338 \\input.zon:1:1: error: expected expression, found 'a document comment'
1339 \\
1340 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1414 }1341 }
1415}1342}
14161343
...@@ -1419,26 +1346,33 @@ test "std.zon failure/oom formatting" {...@@ -1419,26 +1346,33 @@ test "std.zon failure/oom formatting" {
1419 var arena_allocator: ArenaAllocator = .init(gpa);1346 var arena_allocator: ArenaAllocator = .init(gpa);
1420 defer arena_allocator.deinit();1347 defer arena_allocator.deinit();
1421 const arena = arena_allocator.allocator();1348 const arena = arena_allocator.allocator();
1422 var errors: Errors = .init(arena);1349 var errors: Errors = .empty;
1423 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc([]const u8, .{1350
1351 try std.testing.expectError(error.OutOfMemory, fromSlice([]const u8, .{
1424 .gpa = .failing,1352 .gpa = .failing,
1425 .arena = arena,1353 .arena = arena,
1426 .source = "\"foo\"",1354 .source = "\"foo\"",
1427 .errors = &errors,1355 .errors = &errors,
1428 }));1356 }));
1429 try std.testing.expectFmt(1357 try std.testing.expectFmt(
1358 \\input.zon: error.ParseZon
1430 \\1359 \\
1431 , "{f}", .{errors.fmt("input.zon")});1360 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1432}1361}
14331362
1434test "std.zon fromSliceAlloc syntax error" {1363test "std.zon fromSlice syntax error" {
1435 const gpa = std.testing.allocator;1364 const gpa = std.testing.allocator;
1365 var arena_allocator: ArenaAllocator = .init(gpa);
1366 defer arena_allocator.deinit();
1367 const arena = arena_allocator.allocator();
1368 var errors: Errors = .empty;
1436 try std.testing.expectError(1369 try std.testing.expectError(
1437 error.ParseZon,1370 error.ParseZon,
1438 fromSlice(u8, .{1371 fromSliceNoAlloc(u8, .{
1439 .gpa = gpa,1372 .gpa = gpa,
1373 .arena = arena,
1440 .source = ".{",1374 .source = ".{",
1441 .errors = null,1375 .errors = &errors,
1442 }),1376 }),
1443 );1377 );
1444}1378}
...@@ -1448,37 +1382,40 @@ test "std.zon optional" {...@@ -1448,37 +1382,40 @@ test "std.zon optional" {
1448 var arena_allocator: ArenaAllocator = .init(gpa);1382 var arena_allocator: ArenaAllocator = .init(gpa);
1449 defer arena_allocator.deinit();1383 defer arena_allocator.deinit();
1450 const arena = arena_allocator.allocator();1384 const arena = arena_allocator.allocator();
1385 var errors: Errors = .empty;
14511386
1452 // Basic usage1387 // Basic usage
1453 {1388 {
1454 const none = try fromSlice(?u32, .{1389 const none = try fromSliceNoAlloc(?u32, .{
1455 .gpa = gpa,1390 .gpa = gpa,
1391 .arena = arena,
1456 .source = "null",1392 .source = "null",
1457 .errors = null,1393 .errors = &errors,
1458 });1394 });
1459 try std.testing.expect(none == null);1395 try std.testing.expect(none == null);
1460 const some = try fromSlice(?u32, .{1396 const some = try fromSliceNoAlloc(?u32, .{
1461 .gpa = gpa,1397 .gpa = gpa,
1398 .arena = arena,
1462 .source = "1",1399 .source = "1",
1463 .errors = null,1400 .errors = &errors,
1464 });1401 });
1465 try std.testing.expect(some.? == 1);1402 try std.testing.expect(some.? == 1);
1466 }1403 }
14671404
1468 // Deep free1405 // Deep free
1469 {1406 {
1470 const none = try fromSliceAlloc(?[]const u8, .{1407 const none = try fromSlice(?[]const u8, .{
1471 .gpa = gpa,1408 .gpa = gpa,
1472 .arena = arena,1409 .arena = arena,
1473 .source = "null",1410 .source = "null",
1474 .errors = null,1411 .errors = &errors,
1475 });1412 });
1476 try std.testing.expect(none == null);1413 try std.testing.expect(none == null);
1477 const some = try fromSliceAlloc(?[]const u8, .{1414 const some = try fromSlice(?[]const u8, .{
1478 .gpa = gpa,1415 .gpa = gpa,
1479 .arena = arena,1416 .arena = arena,
1480 .source = "\"foo\"",1417 .source = "\"foo\"",
1481 .errors = null,1418 .errors = &errors,
1482 });1419 });
1483 try std.testing.expectEqualStrings("foo", some.?);1420 try std.testing.expectEqualStrings("foo", some.?);
1484 }1421 }
...@@ -1489,47 +1426,54 @@ test "std.zon unions" {...@@ -1489,47 +1426,54 @@ test "std.zon unions" {
1489 var arena_allocator: ArenaAllocator = .init(gpa);1426 var arena_allocator: ArenaAllocator = .init(gpa);
1490 defer arena_allocator.deinit();1427 defer arena_allocator.deinit();
1491 const arena = arena_allocator.allocator();1428 const arena = arena_allocator.allocator();
1429 var errors: Errors = .empty;
14921430
1493 // Unions1431 // Unions
1494 {1432 {
1495 const Tagged = union(enum) { x: f32, @"y y": bool, z, @"z z" };1433 const Tagged = union(enum) { x: f32, @"y y": bool, z, @"z z" };
1496 const Untagged = union { x: f32, @"y y": bool, z: void, @"z z": void };1434 const Untagged = union { x: f32, @"y y": bool, z: void, @"z z": void };
14971435
1498 const tagged_x = try fromSlice(Tagged, .{1436 const tagged_x = try fromSliceNoAlloc(Tagged, .{
1499 .gpa = gpa,1437 .gpa = gpa,
1438 .arena = arena,
1500 .source = ".{.x = 1.5}",1439 .source = ".{.x = 1.5}",
1501 .errors = null,1440 .errors = &errors,
1502 });1441 });
1503 try std.testing.expectEqual(Tagged{ .x = 1.5 }, tagged_x);1442 try std.testing.expectEqual(Tagged{ .x = 1.5 }, tagged_x);
1504 const tagged_y = try fromSlice(Tagged, .{1443 const tagged_y = try fromSliceNoAlloc(Tagged, .{
1505 .gpa = gpa,1444 .gpa = gpa,
1445 .arena = arena,
1506 .source = ".{.@\"y y\" = true}",1446 .source = ".{.@\"y y\" = true}",
1507 .errors = null,1447 .errors = &errors,
1508 });1448 });
1509 try std.testing.expectEqual(Tagged{ .@"y y" = true }, tagged_y);1449 try std.testing.expectEqual(Tagged{ .@"y y" = true }, tagged_y);
1510 const tagged_z_shorthand = try fromSlice(Tagged, .{1450 const tagged_z_shorthand = try fromSliceNoAlloc(Tagged, .{
1511 .gpa = gpa,1451 .gpa = gpa,
1452 .arena = arena,
1512 .source = ".z",1453 .source = ".z",
1513 .errors = null,1454 .errors = &errors,
1514 });1455 });
1515 try std.testing.expectEqual(@as(Tagged, .z), tagged_z_shorthand);1456 try std.testing.expectEqual(@as(Tagged, .z), tagged_z_shorthand);
1516 const tagged_zz_shorthand = try fromSlice(Tagged, .{1457 const tagged_zz_shorthand = try fromSliceNoAlloc(Tagged, .{
1517 .gpa = gpa,1458 .gpa = gpa,
1459 .arena = arena,
1518 .source = ".@\"z z\"",1460 .source = ".@\"z z\"",
1519 .errors = null,1461 .errors = &errors,
1520 });1462 });
1521 try std.testing.expectEqual(@as(Tagged, .@"z z"), tagged_zz_shorthand);1463 try std.testing.expectEqual(@as(Tagged, .@"z z"), tagged_zz_shorthand);
15221464
1523 const untagged_x = try fromSlice(Untagged, .{1465 const untagged_x = try fromSliceNoAlloc(Untagged, .{
1524 .gpa = gpa,1466 .gpa = gpa,
1467 .arena = arena,
1525 .source = ".{.x = 1.5}",1468 .source = ".{.x = 1.5}",
1526 .errors = null,1469 .errors = &errors,
1527 });1470 });
1528 try std.testing.expect(untagged_x.x == 1.5);1471 try std.testing.expect(untagged_x.x == 1.5);
1529 const untagged_y = try fromSlice(Untagged, .{1472 const untagged_y = try fromSliceNoAlloc(Untagged, .{
1530 .gpa = gpa,1473 .gpa = gpa,
1474 .arena = arena,
1531 .source = ".{.@\"y y\" = true}",1475 .source = ".{.@\"y y\" = true}",
1532 .errors = null,1476 .errors = &errors,
1533 });1477 });
1534 try std.testing.expect(untagged_y.@"y y");1478 try std.testing.expect(untagged_y.@"y y");
1535 }1479 }
...@@ -1538,19 +1482,19 @@ test "std.zon unions" {...@@ -1538,19 +1482,19 @@ test "std.zon unions" {
1538 {1482 {
1539 const Union = union(enum) { bar: []const u8, baz: bool };1483 const Union = union(enum) { bar: []const u8, baz: bool };
15401484
1541 const noalloc = try fromSliceAlloc(Union, .{1485 const noalloc = try fromSlice(Union, .{
1542 .gpa = gpa,1486 .gpa = gpa,
1543 .arena = arena,1487 .arena = arena,
1544 .source = ".{.baz = false}",1488 .source = ".{.baz = false}",
1545 .errors = null,1489 .errors = &errors,
1546 });1490 });
1547 try std.testing.expectEqual(Union{ .baz = false }, noalloc);1491 try std.testing.expectEqual(Union{ .baz = false }, noalloc);
15481492
1549 const alloc = try fromSliceAlloc(Union, .{1493 const alloc = try fromSlice(Union, .{
1550 .gpa = gpa,1494 .gpa = gpa,
1551 .arena = arena,1495 .arena = arena,
1552 .source = ".{.bar = \"qux\"}",1496 .source = ".{.bar = \"qux\"}",
1553 .errors = null,1497 .errors = &errors,
1554 });1498 });
1555 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);1499 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);
1556 }1500 }
...@@ -1558,10 +1502,9 @@ test "std.zon unions" {...@@ -1558,10 +1502,9 @@ test "std.zon unions" {
1558 // Unknown field1502 // Unknown field
1559 {1503 {
1560 const Union = union { x: f32, y: f32 };1504 const Union = union { x: f32, y: f32 };
1561 var errors: Errors = .init(arena);
1562 try std.testing.expectError(1505 try std.testing.expectError(
1563 error.ParseZon,1506 error.ParseZon,
1564 fromSliceAlloc(Union, .{1507 fromSlice(Union, .{
1565 .gpa = gpa,1508 .gpa = gpa,
1566 .arena = arena,1509 .arena = arena,
1567 .source = ".{.z=2.5}",1510 .source = ".{.z=2.5}",
...@@ -1569,19 +1512,19 @@ test "std.zon unions" {...@@ -1569,19 +1512,19 @@ test "std.zon unions" {
1569 }),1512 }),
1570 );1513 );
1571 try std.testing.expectFmt(1514 try std.testing.expectFmt(
1515 \\input.zon: error.ParseZon
1572 \\input.zon:1:4: error: unexpected field 'z'1516 \\input.zon:1:4: error: unexpected field 'z'
1573 \\input.zon:1:4: note: supported: 'x', 'y'1517 \\input.zon:1:4: note: supported: 'x', 'y'
1574 \\1518 \\
1575 , "{f}", .{errors.fmt("input.zon")});1519 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1576 }1520 }
15771521
1578 // Explicit void field1522 // Explicit void field
1579 {1523 {
1580 const Union = union(enum) { x: void };1524 const Union = union(enum) { x: void };
1581 var errors: Errors = .init(arena);
1582 try std.testing.expectError(1525 try std.testing.expectError(
1583 error.ParseZon,1526 error.ParseZon,
1584 fromSliceAlloc(Union, .{1527 fromSlice(Union, .{
1585 .gpa = gpa,1528 .gpa = gpa,
1586 .arena = arena,1529 .arena = arena,
1587 .source = ".{.x=1}",1530 .source = ".{.x=1}",
...@@ -1589,18 +1532,18 @@ test "std.zon unions" {...@@ -1589,18 +1532,18 @@ test "std.zon unions" {
1589 }),1532 }),
1590 );1533 );
1591 try std.testing.expectFmt(1534 try std.testing.expectFmt(
1535 \\input.zon: error.ParseZon
1592 \\input.zon:1:6: error: expected type 'void'1536 \\input.zon:1:6: error: expected type 'void'
1593 \\1537 \\
1594 , "{f}", .{errors.fmt("input.zon")});1538 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1595 }1539 }
15961540
1597 // Extra field1541 // Extra field
1598 {1542 {
1599 const Union = union { x: f32, y: bool };1543 const Union = union { x: f32, y: bool };
1600 var errors: Errors = .init(arena);
1601 try std.testing.expectError(1544 try std.testing.expectError(
1602 error.ParseZon,1545 error.ParseZon,
1603 fromSliceAlloc(Union, .{1546 fromSlice(Union, .{
1604 .gpa = gpa,1547 .gpa = gpa,
1605 .arena = arena,1548 .arena = arena,
1606 .source = ".{.x = 1.5, .y = true}",1549 .source = ".{.x = 1.5, .y = true}",
...@@ -1608,18 +1551,18 @@ test "std.zon unions" {...@@ -1608,18 +1551,18 @@ test "std.zon unions" {
1608 }),1551 }),
1609 );1552 );
1610 try std.testing.expectFmt(1553 try std.testing.expectFmt(
1554 \\input.zon: error.ParseZon
1611 \\input.zon:1:2: error: expected union1555 \\input.zon:1:2: error: expected union
1612 \\1556 \\
1613 , "{f}", .{errors.fmt("input.zon")});1557 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1614 }1558 }
16151559
1616 // No fields1560 // No fields
1617 {1561 {
1618 const Union = union { x: f32, y: bool };1562 const Union = union { x: f32, y: bool };
1619 var errors: Errors = .init(arena);
1620 try std.testing.expectError(1563 try std.testing.expectError(
1621 error.ParseZon,1564 error.ParseZon,
1622 fromSliceAlloc(Union, .{1565 fromSlice(Union, .{
1623 .gpa = gpa,1566 .gpa = gpa,
1624 .arena = arena,1567 .arena = arena,
1625 .source = ".{}",1568 .source = ".{}",
...@@ -1627,58 +1570,59 @@ test "std.zon unions" {...@@ -1627,58 +1570,59 @@ test "std.zon unions" {
1627 }),1570 }),
1628 );1571 );
1629 try std.testing.expectFmt(1572 try std.testing.expectFmt(
1573 \\input.zon: error.ParseZon
1630 \\input.zon:1:2: error: expected union1574 \\input.zon:1:2: error: expected union
1631 \\1575 \\
1632 , "{f}", .{errors.fmt("input.zon")});1576 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1633 }1577 }
16341578
1635 // Enum literals cannot coerce into untagged unions1579 // Enum literals cannot coerce into untagged unions
1636 {1580 {
1637 const Union = union { x: void };1581 const Union = union { x: void };
1638 var errors: Errors = .init(arena);1582 try std.testing.expectError(error.ParseZon, fromSlice(Union, .{
1639 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1640 .gpa = gpa,1583 .gpa = gpa,
1641 .arena = arena,1584 .arena = arena,
1642 .source = ".x",1585 .source = ".x",
1643 .errors = &errors,1586 .errors = &errors,
1644 }));1587 }));
1645 try std.testing.expectFmt(1588 try std.testing.expectFmt(
1589 \\input.zon: error.ParseZon
1646 \\input.zon:1:2: error: expected union1590 \\input.zon:1:2: error: expected union
1647 \\1591 \\
1648 , "{f}", .{errors.fmt("input.zon")});1592 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1649 }1593 }
16501594
1651 // Unknown field for enum literal coercion1595 // Unknown field for enum literal coercion
1652 {1596 {
1653 const Union = union(enum) { x: void };1597 const Union = union(enum) { x: void };
1654 var errors: Errors = .init(arena);1598 try std.testing.expectError(error.ParseZon, fromSlice(Union, .{
1655 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1656 .gpa = gpa,1599 .gpa = gpa,
1657 .arena = arena,1600 .arena = arena,
1658 .source = ".y",1601 .source = ".y",
1659 .errors = &errors,1602 .errors = &errors,
1660 }));1603 }));
1661 try std.testing.expectFmt(1604 try std.testing.expectFmt(
1605 \\input.zon: error.ParseZon
1662 \\input.zon:1:2: error: unexpected field 'y'1606 \\input.zon:1:2: error: unexpected field 'y'
1663 \\input.zon:1:2: note: supported: 'x'1607 \\input.zon:1:2: note: supported: 'x'
1664 \\1608 \\
1665 , "{f}", .{errors.fmt("input.zon")});1609 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1666 }1610 }
16671611
1668 // Non void field for enum literal coercion1612 // Non void field for enum literal coercion
1669 {1613 {
1670 const Union = union(enum) { x: f32 };1614 const Union = union(enum) { x: f32 };
1671 var errors: Errors = .init(arena);1615 try std.testing.expectError(error.ParseZon, fromSlice(Union, .{
1672 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
1673 .gpa = gpa,1616 .gpa = gpa,
1674 .arena = arena,1617 .arena = arena,
1675 .source = ".x",1618 .source = ".x",
1676 .errors = &errors,1619 .errors = &errors,
1677 }));1620 }));
1678 try std.testing.expectFmt(1621 try std.testing.expectFmt(
1622 \\input.zon: error.ParseZon
1679 \\input.zon:1:2: error: expected union1623 \\input.zon:1:2: error: expected union
1680 \\1624 \\
1681 , "{f}", .{errors.fmt("input.zon")});1625 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1682 }1626 }
1683}1627}
16841628
...@@ -1687,6 +1631,7 @@ test "std.zon structs" {...@@ -1687,6 +1631,7 @@ test "std.zon structs" {
1687 var arena_allocator: ArenaAllocator = .init(gpa);1631 var arena_allocator: ArenaAllocator = .init(gpa);
1688 defer arena_allocator.deinit();1632 defer arena_allocator.deinit();
1689 const arena = arena_allocator.allocator();1633 const arena = arena_allocator.allocator();
1634 var errors: Errors = .empty;
16901635
1691 // Structs (various sizes tested since they're parsed differently)1636 // Structs (various sizes tested since they're parsed differently)
1692 {1637 {
...@@ -1695,31 +1640,35 @@ test "std.zon structs" {...@@ -1695,31 +1640,35 @@ test "std.zon structs" {
1695 const Vec2 = struct { x: f32, y: f32 };1640 const Vec2 = struct { x: f32, y: f32 };
1696 const Vec3 = struct { x: f32, y: f32, z: f32 };1641 const Vec3 = struct { x: f32, y: f32, z: f32 };
16971642
1698 const zero = try fromSlice(Vec0, .{1643 const zero = try fromSliceNoAlloc(Vec0, .{
1699 .gpa = gpa,1644 .gpa = gpa,
1645 .arena = arena,
1700 .source = ".{}",1646 .source = ".{}",
1701 .errors = null,1647 .errors = &errors,
1702 });1648 });
1703 try std.testing.expectEqual(Vec0{}, zero);1649 try std.testing.expectEqual(Vec0{}, zero);
17041650
1705 const one = try fromSlice(Vec1, .{1651 const one = try fromSliceNoAlloc(Vec1, .{
1706 .gpa = gpa,1652 .gpa = gpa,
1653 .arena = arena,
1707 .source = ".{.x = 1.2}",1654 .source = ".{.x = 1.2}",
1708 .errors = null,1655 .errors = &errors,
1709 });1656 });
1710 try std.testing.expectEqual(Vec1{ .x = 1.2 }, one);1657 try std.testing.expectEqual(Vec1{ .x = 1.2 }, one);
17111658
1712 const two = try fromSlice(Vec2, .{1659 const two = try fromSliceNoAlloc(Vec2, .{
1713 .gpa = gpa,1660 .gpa = gpa,
1661 .arena = arena,
1714 .source = ".{.x = 1.2, .y = 3.4}",1662 .source = ".{.x = 1.2, .y = 3.4}",
1715 .errors = null,1663 .errors = &errors,
1716 });1664 });
1717 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 3.4 }, two);1665 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 3.4 }, two);
17181666
1719 const three = try fromSlice(Vec3, .{1667 const three = try fromSliceNoAlloc(Vec3, .{
1720 .gpa = gpa,1668 .gpa = gpa,
1669 .arena = arena,
1721 .source = ".{.x = 1.2, .y = 3.4, .z = 5.6}",1670 .source = ".{.x = 1.2, .y = 3.4, .z = 5.6}",
1722 .errors = null,1671 .errors = &errors,
1723 });1672 });
1724 try std.testing.expectEqual(Vec3{ .x = 1.2, .y = 3.4, .z = 5.6 }, three);1673 try std.testing.expectEqual(Vec3{ .x = 1.2, .y = 3.4, .z = 5.6 }, three);
1725 }1674 }
...@@ -1728,11 +1677,11 @@ test "std.zon structs" {...@@ -1728,11 +1677,11 @@ test "std.zon structs" {
1728 {1677 {
1729 const Foo = struct { bar: []const u8, baz: []const []const u8 };1678 const Foo = struct { bar: []const u8, baz: []const []const u8 };
17301679
1731 const parsed = try fromSliceAlloc(Foo, .{1680 const parsed = try fromSlice(Foo, .{
1732 .gpa = gpa,1681 .gpa = gpa,
1733 .arena = arena,1682 .arena = arena,
1734 .source = ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",1683 .source = ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
1735 .errors = null,1684 .errors = &errors,
1736 });1685 });
1737 try std.testing.expectEqualDeep(Foo{ .bar = "qux", .baz = &.{ "a", "b" } }, parsed);1686 try std.testing.expectEqualDeep(Foo{ .bar = "qux", .baz = &.{ "a", "b" } }, parsed);
1738 }1687 }
...@@ -1740,49 +1689,52 @@ test "std.zon structs" {...@@ -1740,49 +1689,52 @@ test "std.zon structs" {
1740 // Unknown field1689 // Unknown field
1741 {1690 {
1742 const Vec2 = struct { x: f32, y: f32 };1691 const Vec2 = struct { x: f32, y: f32 };
1743 var errors: Errors = .init(arena);
1744 try std.testing.expectError(1692 try std.testing.expectError(
1745 error.ParseZon,1693 error.ParseZon,
1746 fromSlice(Vec2, .{1694 fromSliceNoAlloc(Vec2, .{
1747 .gpa = gpa,1695 .gpa = gpa,
1696 .arena = arena,
1748 .source = ".{.x=1.5, .z=2.5}",1697 .source = ".{.x=1.5, .z=2.5}",
1749 .errors = &errors,1698 .errors = &errors,
1750 }),1699 }),
1751 );1700 );
1752 try std.testing.expectFmt(1701 try std.testing.expectFmt(
1702 \\input.zon: error.ParseZon
1753 \\input.zon:1:12: error: unexpected field 'z'1703 \\input.zon:1:12: error: unexpected field 'z'
1754 \\input.zon:1:12: note: supported: 'x', 'y'1704 \\input.zon:1:12: note: supported: 'x', 'y'
1755 \\1705 \\
1756 , "{f}", .{errors.fmt("input.zon")});1706 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1757 }1707 }
17581708
1759 // Duplicate field1709 // Duplicate field
1760 {1710 {
1761 const Vec2 = struct { x: f32, y: f32 };1711 const Vec2 = struct { x: f32, y: f32 };
1762 var errors: Errors = .init(arena);
1763 try std.testing.expectError(1712 try std.testing.expectError(
1764 error.ParseZon,1713 error.ParseZon,
1765 fromSlice(Vec2, .{1714 fromSliceNoAlloc(Vec2, .{
1766 .gpa = gpa,1715 .gpa = gpa,
1716 .arena = arena,
1767 .source = ".{.x=1.5, .x=2.5, .x=3.5}",1717 .source = ".{.x=1.5, .x=2.5, .x=3.5}",
1768 .errors = &errors,1718 .errors = &errors,
1769 }),1719 }),
1770 );1720 );
1771 try std.testing.expectFmt(1721 try std.testing.expectFmt(
1722 \\input.zon: error.ParseZon
1772 \\input.zon:1:4: error: duplicate struct field name1723 \\input.zon:1:4: error: duplicate struct field name
1773 \\input.zon:1:12: note: duplicate name here1724 \\input.zon:1:12: note: duplicate name here
1774 \\1725 \\
1775 , "{f}", .{errors.fmt("input.zon")});1726 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1776 }1727 }
17771728
1778 // Ignore unknown fields1729 // Ignore unknown fields
1779 {1730 {
1780 const Vec2 = struct { x: f32, y: f32 = 2.0 };1731 const Vec2 = struct { x: f32, y: f32 = 2.0 };
1781 const parsed = try fromSlice(Vec2, .{1732 const parsed = try fromSliceNoAlloc(Vec2, .{
1782 .gpa = gpa,1733 .gpa = gpa,
1734 .arena = arena,
1783 .source = ".{ .x = 1.0, .z = 3.0 }",1735 .source = ".{ .x = 1.0, .z = 3.0 }",
1784 .ignore_unknown_fields = true,1736 .ignore_unknown_fields = true,
1785 .errors = null,1737 .errors = &errors,
1786 });1738 });
1787 try std.testing.expectEqual(Vec2{ .x = 1.0, .y = 2.0 }, parsed);1739 try std.testing.expectEqual(Vec2{ .x = 1.0, .y = 2.0 }, parsed);
1788 }1740 }
...@@ -1790,47 +1742,50 @@ test "std.zon structs" {...@@ -1790,47 +1742,50 @@ test "std.zon structs" {
1790 // Unknown field when struct has no fields (regression test)1742 // Unknown field when struct has no fields (regression test)
1791 {1743 {
1792 const Vec2 = struct {};1744 const Vec2 = struct {};
1793 var errors: Errors = .init(arena);
1794 try std.testing.expectError(1745 try std.testing.expectError(
1795 error.ParseZon,1746 error.ParseZon,
1796 fromSlice(Vec2, .{1747 fromSliceNoAlloc(Vec2, .{
1797 .gpa = gpa,1748 .gpa = gpa,
1749 .arena = arena,
1798 .source = ".{.x=1.5, .z=2.5}",1750 .source = ".{.x=1.5, .z=2.5}",
1799 .errors = &errors,1751 .errors = &errors,
1800 }),1752 }),
1801 );1753 );
1802 try std.testing.expectFmt(1754 try std.testing.expectFmt(
1755 \\input.zon: error.ParseZon
1803 \\input.zon:1:4: error: unexpected field 'x'1756 \\input.zon:1:4: error: unexpected field 'x'
1804 \\input.zon:1:4: note: none expected1757 \\input.zon:1:4: note: none expected
1805 \\1758 \\
1806 , "{f}", .{errors.fmt("input.zon")});1759 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1807 }1760 }
18081761
1809 // Missing field1762 // Missing field
1810 {1763 {
1811 const Vec2 = struct { x: f32, y: f32 };1764 const Vec2 = struct { x: f32, y: f32 };
1812 var errors: Errors = .init(arena);
1813 try std.testing.expectError(1765 try std.testing.expectError(
1814 error.ParseZon,1766 error.ParseZon,
1815 fromSlice(Vec2, .{1767 fromSliceNoAlloc(Vec2, .{
1816 .gpa = gpa,1768 .gpa = gpa,
1769 .arena = arena,
1817 .source = ".{.x=1.5}",1770 .source = ".{.x=1.5}",
1818 .errors = &errors,1771 .errors = &errors,
1819 }),1772 }),
1820 );1773 );
1821 try std.testing.expectFmt(1774 try std.testing.expectFmt(
1775 \\input.zon: error.ParseZon
1822 \\input.zon:1:2: error: missing required field y1776 \\input.zon:1:2: error: missing required field y
1823 \\1777 \\
1824 , "{f}", .{errors.fmt("input.zon")});1778 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1825 }1779 }
18261780
1827 // Default field1781 // Default field
1828 {1782 {
1829 const Vec2 = struct { x: f32, y: f32 = 1.5 };1783 const Vec2 = struct { x: f32, y: f32 = 1.5 };
1830 const parsed = try fromSlice(Vec2, .{1784 const parsed = try fromSliceNoAlloc(Vec2, .{
1831 .gpa = gpa,1785 .gpa = gpa,
1786 .arena = arena,
1832 .source = ".{.x = 1.2}",1787 .source = ".{.x = 1.2}",
1833 .errors = null,1788 .errors = &errors,
1834 });1789 });
1835 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);1790 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
1836 }1791 }
...@@ -1838,10 +1793,11 @@ test "std.zon structs" {...@@ -1838,10 +1793,11 @@ test "std.zon structs" {
1838 // Comptime field1793 // Comptime field
1839 {1794 {
1840 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };1795 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1841 const parsed = try fromSlice(Vec2, .{1796 const parsed = try fromSliceNoAlloc(Vec2, .{
1842 .gpa = gpa,1797 .gpa = gpa,
1798 .arena = arena,
1843 .source = ".{.x = 1.2}",1799 .source = ".{.x = 1.2}",
1844 .errors = null,1800 .errors = &errors,
1845 });1801 });
1846 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);1802 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
1847 }1803 }
...@@ -1849,27 +1805,29 @@ test "std.zon structs" {...@@ -1849,27 +1805,29 @@ test "std.zon structs" {
1849 // Comptime field assignment1805 // Comptime field assignment
1850 {1806 {
1851 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };1807 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1852 var errors: Errors = .init(arena);1808 const parsed = fromSliceNoAlloc(Vec2, .{
1853 const parsed = fromSlice(Vec2, .{
1854 .gpa = gpa,1809 .gpa = gpa,
1810 .arena = arena,
1855 .source = ".{.x = 1.2, .y = 1.5}",1811 .source = ".{.x = 1.2, .y = 1.5}",
1856 .errors = &errors,1812 .errors = &errors,
1857 });1813 });
1858 try std.testing.expectError(error.ParseZon, parsed);1814 try std.testing.expectError(error.ParseZon, parsed);
1859 try std.testing.expectFmt(1815 try std.testing.expectFmt(
1816 \\input.zon: error.ParseZon
1860 \\input.zon:1:18: error: cannot initialize comptime field1817 \\input.zon:1:18: error: cannot initialize comptime field
1861 \\1818 \\
1862 , "{f}", .{errors.fmt("input.zon")});1819 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1863 }1820 }
18641821
1865 // Enum field (regression test, we were previously getting the field name in an1822 // Enum field (regression test, we were previously getting the field name in an
1866 // incorrect way that broke for enum values)1823 // incorrect way that broke for enum values)
1867 {1824 {
1868 const Vec0 = struct { x: enum { x } };1825 const Vec0 = struct { x: enum { x } };
1869 const parsed = try fromSlice(Vec0, .{1826 const parsed = try fromSliceNoAlloc(Vec0, .{
1870 .gpa = gpa,1827 .gpa = gpa,
1828 .arena = arena,
1871 .source = ".{ .x = .x }",1829 .source = ".{ .x = .x }",
1872 .errors = null,1830 .errors = &errors,
1873 });1831 });
1874 try std.testing.expectEqual(Vec0{ .x = .x }, parsed);1832 try std.testing.expectEqual(Vec0{ .x = .x }, parsed);
1875 }1833 }
...@@ -1877,10 +1835,11 @@ test "std.zon structs" {...@@ -1877,10 +1835,11 @@ test "std.zon structs" {
1877 // Enum field and struct field with @1835 // Enum field and struct field with @
1878 {1836 {
1879 const Vec0 = struct { @"x x": enum { @"x x" } };1837 const Vec0 = struct { @"x x": enum { @"x x" } };
1880 const parsed = try fromSlice(Vec0, .{1838 const parsed = try fromSliceNoAlloc(Vec0, .{
1881 .gpa = gpa,1839 .gpa = gpa,
1840 .arena = arena,
1882 .source = ".{ .@\"x x\" = .@\"x x\" }",1841 .source = ".{ .@\"x x\" = .@\"x x\" }",
1883 .errors = null,1842 .errors = &errors,
1884 });1843 });
1885 try std.testing.expectEqual(Vec0{ .@"x x" = .@"x x" }, parsed);1844 try std.testing.expectEqual(Vec0{ .@"x x" = .@"x x" }, parsed);
1886 }1845 }
...@@ -1889,40 +1848,41 @@ test "std.zon structs" {...@@ -1889,40 +1848,41 @@ test "std.zon structs" {
1889 {1848 {
1890 // Structs1849 // Structs
1891 {1850 {
1892 var errors: Errors = .init(arena);1851 const parsed = fromSliceNoAlloc(struct {}, .{
1893 const parsed = fromSlice(struct {}, .{
1894 .gpa = gpa,1852 .gpa = gpa,
1853 .arena = arena,
1895 .source = "Empty{}",1854 .source = "Empty{}",
1896 .errors = &errors,1855 .errors = &errors,
1897 });1856 });
1898 try std.testing.expectError(error.ParseZon, parsed);1857 try std.testing.expectError(error.ParseZon, parsed);
1899 try std.testing.expectFmt(1858 try std.testing.expectFmt(
1859 \\input.zon: error.ParseZon
1900 \\input.zon:1:1: error: types are not available in ZON1860 \\input.zon:1:1: error: types are not available in ZON
1901 \\input.zon:1:1: note: replace the type with '.'1861 \\input.zon:1:1: note: replace the type with '.'
1902 \\1862 \\
1903 , "{f}", .{errors.fmt("input.zon")});1863 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1904 }1864 }
19051865
1906 // Arrays1866 // Arrays
1907 {1867 {
1908 var errors: Errors = .init(arena);1868 const parsed = fromSliceNoAlloc([3]u8, .{
1909 const parsed = fromSlice([3]u8, .{
1910 .gpa = gpa,1869 .gpa = gpa,
1870 .arena = arena,
1911 .source = "[3]u8{1, 2, 3}",1871 .source = "[3]u8{1, 2, 3}",
1912 .errors = &errors,1872 .errors = &errors,
1913 });1873 });
1914 try std.testing.expectError(error.ParseZon, parsed);1874 try std.testing.expectError(error.ParseZon, parsed);
1915 try std.testing.expectFmt(1875 try std.testing.expectFmt(
1876 \\input.zon: error.ParseZon
1916 \\input.zon:1:1: error: types are not available in ZON1877 \\input.zon:1:1: error: types are not available in ZON
1917 \\input.zon:1:1: note: replace the type with '.'1878 \\input.zon:1:1: note: replace the type with '.'
1918 \\1879 \\
1919 , "{f}", .{errors.fmt("input.zon")});1880 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1920 }1881 }
19211882
1922 // Slices1883 // Slices
1923 {1884 {
1924 var errors: Errors = .init(arena);1885 const parsed = fromSlice([]u8, .{
1925 const parsed = fromSliceAlloc([]u8, .{
1926 .gpa = gpa,1886 .gpa = gpa,
1927 .arena = arena,1887 .arena = arena,
1928 .source = "[]u8{1, 2, 3}",1888 .source = "[]u8{1, 2, 3}",
...@@ -1930,42 +1890,45 @@ test "std.zon structs" {...@@ -1930,42 +1890,45 @@ test "std.zon structs" {
1930 });1890 });
1931 try std.testing.expectError(error.ParseZon, parsed);1891 try std.testing.expectError(error.ParseZon, parsed);
1932 try std.testing.expectFmt(1892 try std.testing.expectFmt(
1893 \\input.zon: error.ParseZon
1933 \\input.zon:1:1: error: types are not available in ZON1894 \\input.zon:1:1: error: types are not available in ZON
1934 \\input.zon:1:1: note: replace the type with '.'1895 \\input.zon:1:1: note: replace the type with '.'
1935 \\1896 \\
1936 , "{f}", .{errors.fmt("input.zon")});1897 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1937 }1898 }
19381899
1939 // Tuples1900 // Tuples
1940 {1901 {
1941 var errors: Errors = .init(arena);1902 const parsed = fromSliceNoAlloc(struct { u8, u8, u8 }, .{
1942 const parsed = fromSlice(struct { u8, u8, u8 }, .{
1943 .gpa = gpa,1903 .gpa = gpa,
1904 .arena = arena,
1944 .source = "Tuple{1, 2, 3}",1905 .source = "Tuple{1, 2, 3}",
1945 .errors = &errors,1906 .errors = &errors,
1946 });1907 });
1947 try std.testing.expectError(error.ParseZon, parsed);1908 try std.testing.expectError(error.ParseZon, parsed);
1948 try std.testing.expectFmt(1909 try std.testing.expectFmt(
1910 \\input.zon: error.ParseZon
1949 \\input.zon:1:1: error: types are not available in ZON1911 \\input.zon:1:1: error: types are not available in ZON
1950 \\input.zon:1:1: note: replace the type with '.'1912 \\input.zon:1:1: note: replace the type with '.'
1951 \\1913 \\
1952 , "{f}", .{errors.fmt("input.zon")});1914 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1953 }1915 }
19541916
1955 // Nested1917 // Nested
1956 {1918 {
1957 var errors: Errors = .init(arena);1919 const parsed = fromSliceNoAlloc(struct {}, .{
1958 const parsed = fromSlice(struct {}, .{
1959 .gpa = gpa,1920 .gpa = gpa,
1921 .arena = arena,
1960 .source = ".{ .x = Tuple{1, 2, 3} }",1922 .source = ".{ .x = Tuple{1, 2, 3} }",
1961 .errors = &errors,1923 .errors = &errors,
1962 });1924 });
1963 try std.testing.expectError(error.ParseZon, parsed);1925 try std.testing.expectError(error.ParseZon, parsed);
1964 try std.testing.expectFmt(1926 try std.testing.expectFmt(
1927 \\input.zon: error.ParseZon
1965 \\input.zon:1:9: error: types are not available in ZON1928 \\input.zon:1:9: error: types are not available in ZON
1966 \\input.zon:1:9: note: replace the type with '.'1929 \\input.zon:1:9: note: replace the type with '.'
1967 \\1930 \\
1968 , "{f}", .{errors.fmt("input.zon")});1931 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
1969 }1932 }
1970 }1933 }
1971}1934}
...@@ -1975,6 +1938,7 @@ test "std.zon tuples" {...@@ -1975,6 +1938,7 @@ test "std.zon tuples" {
1975 var arena_allocator: ArenaAllocator = .init(gpa);1938 var arena_allocator: ArenaAllocator = .init(gpa);
1976 defer arena_allocator.deinit();1939 defer arena_allocator.deinit();
1977 const arena = arena_allocator.allocator();1940 const arena = arena_allocator.allocator();
1941 var errors: Errors = .empty;
19781942
1979 // Structs (various sizes tested since they're parsed differently)1943 // Structs (various sizes tested since they're parsed differently)
1980 {1944 {
...@@ -1983,31 +1947,35 @@ test "std.zon tuples" {...@@ -1983,31 +1947,35 @@ test "std.zon tuples" {
1983 const Tuple2 = struct { f32, bool };1947 const Tuple2 = struct { f32, bool };
1984 const Tuple3 = struct { f32, bool, u8 };1948 const Tuple3 = struct { f32, bool, u8 };
19851949
1986 const zero = try fromSlice(Tuple0, .{1950 const zero = try fromSliceNoAlloc(Tuple0, .{
1987 .gpa = gpa,1951 .gpa = gpa,
1952 .arena = arena,
1988 .source = ".{}",1953 .source = ".{}",
1989 .errors = null,1954 .errors = &errors,
1990 });1955 });
1991 try std.testing.expectEqual(Tuple0{}, zero);1956 try std.testing.expectEqual(Tuple0{}, zero);
19921957
1993 const one = try fromSlice(Tuple1, .{1958 const one = try fromSliceNoAlloc(Tuple1, .{
1994 .gpa = gpa,1959 .gpa = gpa,
1960 .arena = arena,
1995 .source = ".{1.2}",1961 .source = ".{1.2}",
1996 .errors = null,1962 .errors = &errors,
1997 });1963 });
1998 try std.testing.expectEqual(Tuple1{1.2}, one);1964 try std.testing.expectEqual(Tuple1{1.2}, one);
19991965
2000 const two = try fromSlice(Tuple2, .{1966 const two = try fromSliceNoAlloc(Tuple2, .{
2001 .gpa = gpa,1967 .gpa = gpa,
1968 .arena = arena,
2002 .source = ".{1.2, true}",1969 .source = ".{1.2, true}",
2003 .errors = null,1970 .errors = &errors,
2004 });1971 });
2005 try std.testing.expectEqual(Tuple2{ 1.2, true }, two);1972 try std.testing.expectEqual(Tuple2{ 1.2, true }, two);
20061973
2007 const three = try fromSlice(Tuple3, .{1974 const three = try fromSliceNoAlloc(Tuple3, .{
2008 .gpa = gpa,1975 .gpa = gpa,
1976 .arena = arena,
2009 .source = ".{1.2, false, 3}",1977 .source = ".{1.2, false, 3}",
2010 .errors = null,1978 .errors = &errors,
2011 });1979 });
2012 try std.testing.expectEqual(Tuple3{ 1.2, false, 3 }, three);1980 try std.testing.expectEqual(Tuple3{ 1.2, false, 3 }, three);
2013 }1981 }
...@@ -2015,11 +1983,11 @@ test "std.zon tuples" {...@@ -2015,11 +1983,11 @@ test "std.zon tuples" {
2015 // Deep free1983 // Deep free
2016 {1984 {
2017 const Tuple = struct { []const u8, []const u8 };1985 const Tuple = struct { []const u8, []const u8 };
2018 const parsed = try fromSliceAlloc(Tuple, .{1986 const parsed = try fromSlice(Tuple, .{
2019 .gpa = gpa,1987 .gpa = gpa,
2020 .arena = arena,1988 .arena = arena,
2021 .source = ".{\"hello\", \"world\"}",1989 .source = ".{\"hello\", \"world\"}",
2022 .errors = null,1990 .errors = &errors,
2023 });1991 });
2024 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);1992 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);
2025 }1993 }
...@@ -2027,79 +1995,87 @@ test "std.zon tuples" {...@@ -2027,79 +1995,87 @@ test "std.zon tuples" {
2027 // Extra field1995 // Extra field
2028 {1996 {
2029 const Tuple = struct { f32, bool };1997 const Tuple = struct { f32, bool };
2030 var errors: Errors = .init(arena);
2031 try std.testing.expectError(1998 try std.testing.expectError(
2032 error.ParseZon,1999 error.ParseZon,
2033 fromSlice(Tuple, .{2000 fromSliceNoAlloc(Tuple, .{
2034 .gpa = gpa,2001 .gpa = gpa,
2002 .arena = arena,
2035 .source = ".{0.5, true, 123}",2003 .source = ".{0.5, true, 123}",
2036 .errors = &errors,2004 .errors = &errors,
2037 }),2005 }),
2038 );2006 );
2039 try std.testing.expectFmt(2007 try std.testing.expectFmt(
2008 \\input.zon: error.ParseZon
2040 \\input.zon:1:14: error: index 2 outside of tuple length 22009 \\input.zon:1:14: error: index 2 outside of tuple length 2
2041 \\2010 \\
2042 , "{f}", .{errors.fmt("input.zon")});2011 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2043 }2012 }
20442013
2045 // Extra field2014 // Extra field
2046 {2015 {
2047 const Tuple = struct { f32, bool };2016 const Tuple = struct { f32, bool };
2048 var errors: Errors = .init(arena);
2049 try std.testing.expectError(2017 try std.testing.expectError(
2050 error.ParseZon,2018 error.ParseZon,
2051 fromSlice(Tuple, .{2019 fromSliceNoAlloc(Tuple, .{
2052 .gpa = gpa,2020 .gpa = gpa,
2021 .arena = arena,
2053 .source = ".{0.5}",2022 .source = ".{0.5}",
2054 .errors = &errors,2023 .errors = &errors,
2055 }),2024 }),
2056 );2025 );
2057 try std.testing.expectFmt(2026 try std.testing.expectFmt(
2027 \\input.zon: error.ParseZon
2058 \\input.zon:1:2: error: missing tuple field with index 12028 \\input.zon:1:2: error: missing tuple field with index 1
2059 \\2029 \\
2060 , "{f}", .{errors.fmt("input.zon")});2030 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2061 }2031 }
20622032
2063 // Tuple with unexpected field names2033 // Tuple with unexpected field names
2064 {2034 {
2065 const Tuple = struct { f32 };2035 const Tuple = struct { f32 };
2066 var errors: Errors = .init(arena);
2067 try std.testing.expectError(2036 try std.testing.expectError(
2068 error.ParseZon,2037 error.ParseZon,
2069 fromSlice(Tuple, .{2038 fromSliceNoAlloc(Tuple, .{
2070 .gpa = gpa,2039 .gpa = gpa,
2040 .arena = arena,
2071 .source = ".{.foo = 10.0}",2041 .source = ".{.foo = 10.0}",
2072 .errors = &errors,2042 .errors = &errors,
2073 }),2043 }),
2074 );2044 );
2075 try std.testing.expectFmt("input.zon:1:2: error: expected tuple\n", "{f}", .{errors.fmt("input.zon")});2045 try std.testing.expectFmt(
2046 \\input.zon: error.ParseZon
2047 \\input.zon:1:2: error: expected tuple
2048 \\
2049 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2076 }2050 }
20772051
2078 // Struct with missing field names2052 // Struct with missing field names
2079 {2053 {
2080 const Struct = struct { foo: f32 };2054 const Struct = struct { foo: f32 };
2081 var errors: Errors = .init(arena);
2082 try std.testing.expectError(2055 try std.testing.expectError(
2083 error.ParseZon,2056 error.ParseZon,
2084 fromSlice(Struct, .{2057 fromSliceNoAlloc(Struct, .{
2085 .gpa = gpa,2058 .gpa = gpa,
2059 .arena = arena,
2086 .source = ".{10.0}",2060 .source = ".{10.0}",
2087 .errors = &errors,2061 .errors = &errors,
2088 }),2062 }),
2089 );2063 );
2090 try std.testing.expectFmt(2064 try std.testing.expectFmt(
2065 \\input.zon: error.ParseZon
2091 \\input.zon:1:2: error: expected struct2066 \\input.zon:1:2: error: expected struct
2092 \\2067 \\
2093 , "{f}", .{errors.fmt("input.zon")});2068 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2094 }2069 }
20952070
2096 // Comptime field2071 // Comptime field
2097 {2072 {
2098 const Vec2 = struct { f32, comptime f32 = 1.5 };2073 const Vec2 = struct { f32, comptime f32 = 1.5 };
2099 const parsed = try fromSlice(Vec2, .{2074 const parsed = try fromSliceNoAlloc(Vec2, .{
2100 .gpa = gpa,2075 .gpa = gpa,
2076 .arena = arena,
2101 .source = ".{ 1.2 }",2077 .source = ".{ 1.2 }",
2102 .errors = null,2078 .errors = &errors,
2103 });2079 });
2104 try std.testing.expectEqual(Vec2{ 1.2, 1.5 }, parsed);2080 try std.testing.expectEqual(Vec2{ 1.2, 1.5 }, parsed);
2105 }2081 }
...@@ -2107,17 +2083,18 @@ test "std.zon tuples" {...@@ -2107,17 +2083,18 @@ test "std.zon tuples" {
2107 // Comptime field assignment2083 // Comptime field assignment
2108 {2084 {
2109 const Vec2 = struct { f32, comptime f32 = 1.5 };2085 const Vec2 = struct { f32, comptime f32 = 1.5 };
2110 var errors: Errors = .init(arena);2086 const parsed = fromSliceNoAlloc(Vec2, .{
2111 const parsed = fromSlice(Vec2, .{
2112 .gpa = gpa,2087 .gpa = gpa,
2088 .arena = arena,
2113 .source = ".{ 1.2, 1.5}",2089 .source = ".{ 1.2, 1.5}",
2114 .errors = &errors,2090 .errors = &errors,
2115 });2091 });
2116 try std.testing.expectError(error.ParseZon, parsed);2092 try std.testing.expectError(error.ParseZon, parsed);
2117 try std.testing.expectFmt(2093 try std.testing.expectFmt(
2094 \\input.zon: error.ParseZon
2118 \\input.zon:1:9: error: cannot initialize comptime field2095 \\input.zon:1:9: error: cannot initialize comptime field
2119 \\2096 \\
2120 , "{f}", .{errors.fmt("input.zon")});2097 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2121 }2098 }
2122}2099}
21232100
...@@ -2129,50 +2106,57 @@ test "std.zon arrays and slices" {...@@ -2129,50 +2106,57 @@ test "std.zon arrays and slices" {
2129 var arena_allocator: ArenaAllocator = .init(gpa);2106 var arena_allocator: ArenaAllocator = .init(gpa);
2130 defer arena_allocator.deinit();2107 defer arena_allocator.deinit();
2131 const arena = arena_allocator.allocator();2108 const arena = arena_allocator.allocator();
2109 var errors: Errors = .empty;
21322110
2133 // Literals2111 // Literals
2134 {2112 {
2135 // Arrays2113 // Arrays
2136 {2114 {
2137 const zero = try fromSlice([0]u8, .{2115 const zero = try fromSliceNoAlloc([0]u8, .{
2138 .gpa = gpa,2116 .gpa = gpa,
2117 .arena = arena,
2139 .source = ".{}",2118 .source = ".{}",
2140 .errors = null,2119 .errors = &errors,
2141 });2120 });
2142 try std.testing.expectEqualSlices(u8, &@as([0]u8, .{}), &zero);2121 try std.testing.expectEqualSlices(u8, &@as([0]u8, .{}), &zero);
21432122
2144 const one = try fromSlice([1]u8, .{2123 const one = try fromSliceNoAlloc([1]u8, .{
2145 .gpa = gpa,2124 .gpa = gpa,
2125 .arena = arena,
2146 .source = ".{'a'}",2126 .source = ".{'a'}",
2147 .errors = null,2127 .errors = &errors,
2148 });2128 });
2149 try std.testing.expectEqualSlices(u8, &@as([1]u8, .{'a'}), &one);2129 try std.testing.expectEqualSlices(u8, &@as([1]u8, .{'a'}), &one);
21502130
2151 const two = try fromSlice([2]u8, .{2131 const two = try fromSliceNoAlloc([2]u8, .{
2152 .gpa = gpa,2132 .gpa = gpa,
2133 .arena = arena,
2153 .source = ".{'a', 'b'}",2134 .source = ".{'a', 'b'}",
2154 .errors = null,2135 .errors = &errors,
2155 });2136 });
2156 try std.testing.expectEqualSlices(u8, &@as([2]u8, .{ 'a', 'b' }), &two);2137 try std.testing.expectEqualSlices(u8, &@as([2]u8, .{ 'a', 'b' }), &two);
21572138
2158 const two_comma = try fromSlice([2]u8, .{2139 const two_comma = try fromSliceNoAlloc([2]u8, .{
2159 .gpa = gpa,2140 .gpa = gpa,
2141 .arena = arena,
2160 .source = ".{'a', 'b',}",2142 .source = ".{'a', 'b',}",
2161 .errors = null,2143 .errors = &errors,
2162 });2144 });
2163 try std.testing.expectEqualSlices(u8, &@as([2]u8, .{ 'a', 'b' }), &two_comma);2145 try std.testing.expectEqualSlices(u8, &@as([2]u8, .{ 'a', 'b' }), &two_comma);
21642146
2165 const three = try fromSlice([3]u8, .{2147 const three = try fromSliceNoAlloc([3]u8, .{
2166 .gpa = gpa,2148 .gpa = gpa,
2149 .arena = arena,
2167 .source = ".{'a', 'b', 'c'}",2150 .source = ".{'a', 'b', 'c'}",
2168 .errors = null,2151 .errors = &errors,
2169 });2152 });
2170 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, &three);2153 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, &three);
21712154
2172 const sentinel = try fromSlice([3:'z']u8, .{2155 const sentinel = try fromSliceNoAlloc([3:'z']u8, .{
2173 .gpa = gpa,2156 .gpa = gpa,
2157 .arena = arena,
2174 .source = ".{'a', 'b', 'c'}",2158 .source = ".{'a', 'b', 'c'}",
2175 .errors = null,2159 .errors = &errors,
2176 });2160 });
2177 const expected_sentinel: [3:'z']u8 = .{ 'a', 'b', 'c' };2161 const expected_sentinel: [3:'z']u8 = .{ 'a', 'b', 'c' };
2178 try std.testing.expectEqualSlices(u8, &expected_sentinel, &sentinel);2162 try std.testing.expectEqualSlices(u8, &expected_sentinel, &sentinel);
...@@ -2180,51 +2164,51 @@ test "std.zon arrays and slices" {...@@ -2180,51 +2164,51 @@ test "std.zon arrays and slices" {
21802164
2181 // Slice literals2165 // Slice literals
2182 {2166 {
2183 const zero = try fromSliceAlloc([]const u8, .{2167 const zero = try fromSlice([]const u8, .{
2184 .gpa = gpa,2168 .gpa = gpa,
2185 .arena = arena,2169 .arena = arena,
2186 .source = ".{}",2170 .source = ".{}",
2187 .errors = null,2171 .errors = &errors,
2188 });2172 });
2189 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);2173 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);
21902174
2191 const one = try fromSliceAlloc([]u8, .{2175 const one = try fromSlice([]u8, .{
2192 .gpa = gpa,2176 .gpa = gpa,
2193 .arena = arena,2177 .arena = arena,
2194 .source = ".{'a'}",2178 .source = ".{'a'}",
2195 .errors = null,2179 .errors = &errors,
2196 });2180 });
2197 try std.testing.expectEqualSlices(u8, &.{'a'}, one);2181 try std.testing.expectEqualSlices(u8, &.{'a'}, one);
21982182
2199 const two = try fromSliceAlloc([]const u8, .{2183 const two = try fromSlice([]const u8, .{
2200 .gpa = gpa,2184 .gpa = gpa,
2201 .arena = arena,2185 .arena = arena,
2202 .source = ".{'a', 'b'}",2186 .source = ".{'a', 'b'}",
2203 .errors = null,2187 .errors = &errors,
2204 });2188 });
2205 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);2189 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);
22062190
2207 const two_comma = try fromSliceAlloc([]const u8, .{2191 const two_comma = try fromSlice([]const u8, .{
2208 .gpa = gpa,2192 .gpa = gpa,
2209 .arena = arena,2193 .arena = arena,
2210 .source = ".{'a', 'b',}",2194 .source = ".{'a', 'b',}",
2211 .errors = null,2195 .errors = &errors,
2212 });2196 });
2213 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);2197 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);
22142198
2215 const three = try fromSliceAlloc([]u8, .{2199 const three = try fromSlice([]u8, .{
2216 .gpa = gpa,2200 .gpa = gpa,
2217 .arena = arena,2201 .arena = arena,
2218 .source = ".{'a', 'b', 'c'}",2202 .source = ".{'a', 'b', 'c'}",
2219 .errors = null,2203 .errors = &errors,
2220 });2204 });
2221 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);2205 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);
22222206
2223 const sentinel = try fromSliceAlloc([:'z']const u8, .{2207 const sentinel = try fromSlice([:'z']const u8, .{
2224 .gpa = gpa,2208 .gpa = gpa,
2225 .arena = arena,2209 .arena = arena,
2226 .source = ".{'a', 'b', 'c'}",2210 .source = ".{'a', 'b', 'c'}",
2227 .errors = null,2211 .errors = &errors,
2228 });2212 });
2229 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };2213 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };
2230 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);2214 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);
...@@ -2235,11 +2219,11 @@ test "std.zon arrays and slices" {...@@ -2235,11 +2219,11 @@ test "std.zon arrays and slices" {
2235 {2219 {
2236 // Arrays2220 // Arrays
2237 {2221 {
2238 const parsed = try fromSliceAlloc([1][]const u8, .{2222 const parsed = try fromSlice([1][]const u8, .{
2239 .gpa = gpa,2223 .gpa = gpa,
2240 .arena = arena,2224 .arena = arena,
2241 .source = ".{\"abc\"}",2225 .source = ".{\"abc\"}",
2242 .errors = null,2226 .errors = &errors,
2243 });2227 });
2244 const expected: [1][]const u8 = .{"abc"};2228 const expected: [1][]const u8 = .{"abc"};
2245 try std.testing.expectEqualDeep(expected, parsed);2229 try std.testing.expectEqualDeep(expected, parsed);
...@@ -2247,11 +2231,11 @@ test "std.zon arrays and slices" {...@@ -2247,11 +2231,11 @@ test "std.zon arrays and slices" {
22472231
2248 // Slice literals2232 // Slice literals
2249 {2233 {
2250 const parsed = try fromSliceAlloc([]const []const u8, .{2234 const parsed = try fromSlice([]const []const u8, .{
2251 .gpa = gpa,2235 .gpa = gpa,
2252 .arena = arena,2236 .arena = arena,
2253 .source = ".{\"abc\"}",2237 .source = ".{\"abc\"}",
2254 .errors = null,2238 .errors = &errors,
2255 });2239 });
2256 const expected: []const []const u8 = &.{"abc"};2240 const expected: []const []const u8 = &.{"abc"};
2257 try std.testing.expectEqualDeep(expected, parsed);2241 try std.testing.expectEqualDeep(expected, parsed);
...@@ -2262,10 +2246,11 @@ test "std.zon arrays and slices" {...@@ -2262,10 +2246,11 @@ test "std.zon arrays and slices" {
2262 {2246 {
2263 // Arrays2247 // Arrays
2264 {2248 {
2265 const sentinel = try fromSlice([1:2]u8, .{2249 const sentinel = try fromSliceNoAlloc([1:2]u8, .{
2266 .gpa = gpa,2250 .gpa = gpa,
2251 .arena = arena,
2267 .source = ".{1}",2252 .source = ".{1}",
2268 .errors = null,2253 .errors = &errors,
2269 });2254 });
2270 try std.testing.expectEqual(@as(usize, 1), sentinel.len);2255 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
2271 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);2256 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
...@@ -2274,11 +2259,11 @@ test "std.zon arrays and slices" {...@@ -2274,11 +2259,11 @@ test "std.zon arrays and slices" {
22742259
2275 // Slice literals2260 // Slice literals
2276 {2261 {
2277 const sentinel = try fromSliceAlloc([:2]align(4) u8, .{2262 const sentinel = try fromSlice([:2]align(4) u8, .{
2278 .gpa = gpa,2263 .gpa = gpa,
2279 .arena = arena,2264 .arena = arena,
2280 .source = ".{1}",2265 .source = ".{1}",
2281 .errors = null,2266 .errors = &errors,
2282 });2267 });
2283 try std.testing.expectEqual(@as(usize, 1), sentinel.len);2268 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
2284 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);2269 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
...@@ -2288,101 +2273,112 @@ test "std.zon arrays and slices" {...@@ -2288,101 +2273,112 @@ test "std.zon arrays and slices" {
22882273
2289 // Expect 0 find 32274 // Expect 0 find 3
2290 {2275 {
2291 var errors: Errors = .init(arena);
2292 try std.testing.expectError(2276 try std.testing.expectError(
2293 error.ParseZon,2277 error.ParseZon,
2294 fromSlice([0]u8, .{2278 fromSliceNoAlloc([0]u8, .{
2295 .gpa = gpa,2279 .gpa = gpa,
2280 .arena = arena,
2296 .source = ".{'a', 'b', 'c'}",2281 .source = ".{'a', 'b', 'c'}",
2297 .errors = &errors,2282 .errors = &errors,
2298 }),2283 }),
2299 );2284 );
2300 try std.testing.expectFmt(2285 try std.testing.expectFmt(
2286 \\input.zon: error.ParseZon
2301 \\input.zon:1:3: error: index 0 outside of array of length 02287 \\input.zon:1:3: error: index 0 outside of array of length 0
2302 \\2288 \\
2303 , "{f}", .{errors.fmt("input.zon")});2289 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2304 }2290 }
23052291
2306 // Expect 1 find 22292 // Expect 1 find 2
2307 {2293 {
2308 var errors: Errors = .init(arena);
2309 try std.testing.expectError(2294 try std.testing.expectError(
2310 error.ParseZon,2295 error.ParseZon,
2311 fromSlice([1]u8, .{2296 fromSliceNoAlloc([1]u8, .{
2312 .gpa = gpa,2297 .gpa = gpa,
2298 .arena = arena,
2313 .source = ".{'a', 'b'}",2299 .source = ".{'a', 'b'}",
2314 .errors = &errors,2300 .errors = &errors,
2315 }),2301 }),
2316 );2302 );
2317 try std.testing.expectFmt(2303 try std.testing.expectFmt(
2304 \\input.zon: error.ParseZon
2318 \\input.zon:1:8: error: index 1 outside of array of length 12305 \\input.zon:1:8: error: index 1 outside of array of length 1
2319 \\2306 \\
2320 , "{f}", .{errors.fmt("input.zon")});2307 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2321 }2308 }
23222309
2323 // Expect 2 find 12310 // Expect 2 find 1
2324 {2311 {
2325 var errors: Errors = .init(arena);
2326 try std.testing.expectError(2312 try std.testing.expectError(
2327 error.ParseZon,2313 error.ParseZon,
2328 fromSlice([2]u8, .{2314 fromSliceNoAlloc([2]u8, .{
2329 .gpa = gpa,2315 .gpa = gpa,
2316 .arena = arena,
2330 .source = ".{'a'}",2317 .source = ".{'a'}",
2331 .errors = &errors,2318 .errors = &errors,
2332 }),2319 }),
2333 );2320 );
2334 try std.testing.expectFmt(2321 try std.testing.expectFmt(
2322 \\input.zon: error.ParseZon
2335 \\input.zon:1:2: error: expected 2 array elements; found 12323 \\input.zon:1:2: error: expected 2 array elements; found 1
2336 \\2324 \\
2337 , "{f}", .{errors.fmt("input.zon")});2325 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2338 }2326 }
23392327
2340 // Expect 3 find 02328 // Expect 3 find 0
2341 {2329 {
2342 var errors: Errors = .init(arena);
2343 try std.testing.expectError(2330 try std.testing.expectError(
2344 error.ParseZon,2331 error.ParseZon,
2345 fromSlice([3]u8, .{2332 fromSliceNoAlloc([3]u8, .{
2346 .gpa = gpa,2333 .gpa = gpa,
2334 .arena = arena,
2347 .source = ".{}",2335 .source = ".{}",
2348 .errors = &errors,2336 .errors = &errors,
2349 }),2337 }),
2350 );2338 );
2351 try std.testing.expectFmt("input.zon:1:2: error: expected 3 array elements; found 0\n", "{f}", .{errors.fmt("input.zon")});2339 try std.testing.expectFmt(
2340 \\input.zon: error.ParseZon
2341 \\input.zon:1:2: error: expected 3 array elements; found 0
2342 \\
2343 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2352 }2344 }
23532345
2354 // Wrong inner type2346 // Wrong inner type
2355 {2347 {
2356 // Array2348 // Array
2357 {2349 {
2358 var errors: Errors = .init(arena);
2359 try std.testing.expectError(2350 try std.testing.expectError(
2360 error.ParseZon,2351 error.ParseZon,
2361 fromSlice([3]bool, .{2352 fromSliceNoAlloc([3]bool, .{
2362 .gpa = gpa,2353 .gpa = gpa,
2354 .arena = arena,
2363 .source = ".{'a', 'b', 'c'}",2355 .source = ".{'a', 'b', 'c'}",
2364 .errors = &errors,2356 .errors = &errors,
2365 }),2357 }),
2366 );2358 );
2367 try std.testing.expectFmt(2359 try std.testing.expectFmt(
2360 \\input.zon: error.ParseZon
2368 \\input.zon:1:3: error: expected type 'bool'2361 \\input.zon:1:3: error: expected type 'bool'
2369 \\2362 \\
2370 , "{f}", .{errors.fmt("input.zon")});2363 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2371 }2364 }
23722365
2373 // Slice2366 // Slice
2374 {2367 {
2375 var errors: Errors = .init(arena);
2376 try std.testing.expectError(2368 try std.testing.expectError(
2377 error.ParseZon,2369 error.ParseZon,
2378 fromSliceAlloc([]bool, .{2370 fromSlice([]bool, .{
2379 .gpa = gpa,2371 .gpa = gpa,
2380 .arena = arena,2372 .arena = arena,
2381 .source = ".{'a', 'b', 'c'}",2373 .source = ".{'a', 'b', 'c'}",
2382 .errors = &errors,2374 .errors = &errors,
2383 }),2375 }),
2384 );2376 );
2385 try std.testing.expectFmt("input.zon:1:3: error: expected type 'bool'\n", "{f}", .{errors.fmt("input.zon")});2377 try std.testing.expectFmt(
2378 \\input.zon: error.ParseZon
2379 \\input.zon:1:3: error: expected type 'bool'
2380 \\
2381 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2386 }2382 }
2387 }2383 }
23882384
...@@ -2390,43 +2386,47 @@ test "std.zon arrays and slices" {...@@ -2390,43 +2386,47 @@ test "std.zon arrays and slices" {
2390 {2386 {
2391 // Array2387 // Array
2392 {2388 {
2393 var errors: Errors = .init(arena);
2394 try std.testing.expectError(2389 try std.testing.expectError(
2395 error.ParseZon,2390 error.ParseZon,
2396 fromSlice([3]u8, .{2391 fromSliceNoAlloc([3]u8, .{
2397 .gpa = gpa,2392 .gpa = gpa,
2393 .arena = arena,
2398 .source = "'a'",2394 .source = "'a'",
2399 .errors = &errors,2395 .errors = &errors,
2400 }),2396 }),
2401 );2397 );
2402 try std.testing.expectFmt(2398 try std.testing.expectFmt(
2399 \\input.zon: error.ParseZon
2403 \\input.zon:1:1: error: expected array2400 \\input.zon:1:1: error: expected array
2404 \\2401 \\
2405 , "{f}", .{errors.fmt("input.zon")});2402 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2406 }2403 }
24072404
2408 // Slice2405 // Slice
2409 {2406 {
2410 var errors: Errors = .init(arena);
2411 try std.testing.expectError(2407 try std.testing.expectError(
2412 error.ParseZon,2408 error.ParseZon,
2413 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "'a'", .errors = &errors }),2409 fromSlice([]u8, .{ .gpa = gpa, .arena = arena, .source = "'a'", .errors = &errors }),
2414 );2410 );
2415 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});2411 try std.testing.expectFmt(
2412 \\input.zon: error.ParseZon
2413 \\input.zon:1:1: error: expected array
2414 \\
2415 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2416 }2416 }
2417 }2417 }
24182418
2419 // Address of is not allowed (indirection for slices in ZON is implicit)2419 // Address of is not allowed (indirection for slices in ZON is implicit)
2420 {2420 {
2421 var errors: Errors = .init(arena);
2422 try std.testing.expectError(2421 try std.testing.expectError(
2423 error.ParseZon,2422 error.ParseZon,
2424 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = " &.{'a', 'b', 'c'}", .errors = &errors }),2423 fromSlice([]u8, .{ .gpa = gpa, .arena = arena, .source = " &.{'a', 'b', 'c'}", .errors = &errors }),
2425 );2424 );
2426 try std.testing.expectFmt(2425 try std.testing.expectFmt(
2426 \\input.zon: error.ParseZon
2427 \\input.zon:1:3: error: pointers are not available in ZON2427 \\input.zon:1:3: error: pointers are not available in ZON
2428 \\2428 \\
2429 , "{f}", .{errors.fmt("input.zon")});2429 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2430 }2430 }
2431}2431}
24322432
...@@ -2435,36 +2435,37 @@ test "std.zon string literal" {...@@ -2435,36 +2435,37 @@ test "std.zon string literal" {
2435 var arena_allocator: ArenaAllocator = .init(gpa);2435 var arena_allocator: ArenaAllocator = .init(gpa);
2436 defer arena_allocator.deinit();2436 defer arena_allocator.deinit();
2437 const arena = arena_allocator.allocator();2437 const arena = arena_allocator.allocator();
2438 var errors: Errors = .empty;
24382439
2439 // Basic string literal2440 // Basic string literal
2440 {2441 {
2441 const parsed = try fromSliceAlloc([]const u8, .{2442 const parsed = try fromSlice([]const u8, .{
2442 .gpa = gpa,2443 .gpa = gpa,
2443 .arena = arena,2444 .arena = arena,
2444 .source = "\"abc\"",2445 .source = "\"abc\"",
2445 .errors = null,2446 .errors = &errors,
2446 });2447 });
2447 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);2448 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);
2448 }2449 }
24492450
2450 // String literal with escape characters2451 // String literal with escape characters
2451 {2452 {
2452 const parsed = try fromSliceAlloc([]const u8, .{2453 const parsed = try fromSlice([]const u8, .{
2453 .gpa = gpa,2454 .gpa = gpa,
2454 .arena = arena,2455 .arena = arena,
2455 .source = "\"ab\\nc\"",2456 .source = "\"ab\\nc\"",
2456 .errors = null,2457 .errors = &errors,
2457 });2458 });
2458 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);2459 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);
2459 }2460 }
24602461
2461 // String literal with embedded null2462 // String literal with embedded null
2462 {2463 {
2463 const parsed = try fromSliceAlloc([]const u8, .{2464 const parsed = try fromSlice([]const u8, .{
2464 .gpa = gpa,2465 .gpa = gpa,
2465 .arena = arena,2466 .arena = arena,
2466 .source = "\"ab\\x00c\"",2467 .source = "\"ab\\x00c\"",
2467 .errors = null,2468 .errors = &errors,
2468 });2469 });
2469 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);2470 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);
2470 }2471 }
...@@ -2472,24 +2473,27 @@ test "std.zon string literal" {...@@ -2472,24 +2473,27 @@ test "std.zon string literal" {
2472 // Passing string literal to a mutable slice2473 // Passing string literal to a mutable slice
2473 {2474 {
2474 {2475 {
2475 var errors: Errors = .init(arena);
2476 try std.testing.expectError(2476 try std.testing.expectError(
2477 error.ParseZon,2477 error.ParseZon,
2478 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\"abcd\"", .errors = &errors }),2478 fromSlice([]u8, .{ .gpa = gpa, .arena = arena, .source = "\"abcd\"", .errors = &errors }),
2479 );2479 );
2480 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});2480 try std.testing.expectFmt(
2481 \\input.zon: error.ParseZon
2482 \\input.zon:1:1: error: expected array
2483 \\
2484 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2481 }2485 }
24822486
2483 {2487 {
2484 var errors: Errors = .init(arena);
2485 try std.testing.expectError(2488 try std.testing.expectError(
2486 error.ParseZon,2489 error.ParseZon,
2487 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\abcd", .errors = &errors }),2490 fromSlice([]u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\abcd", .errors = &errors }),
2488 );2491 );
2489 try std.testing.expectFmt(2492 try std.testing.expectFmt(
2493 \\input.zon: error.ParseZon
2490 \\input.zon:1:1: error: expected array2494 \\input.zon:1:1: error: expected array
2491 \\2495 \\
2492 , "{f}", .{errors.fmt("input.zon")});2496 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2493 }2497 }
2494 }2498 }
24952499
...@@ -2500,54 +2504,59 @@ test "std.zon string literal" {...@@ -2500,54 +2504,59 @@ test "std.zon string literal" {
2500 defer ast.deinit(gpa);2504 defer ast.deinit(gpa);
2501 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });2505 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
2502 defer zoir.deinit(gpa);2506 defer zoir.deinit(gpa);
2503 var errors: Errors = .init(arena);
2504 try std.testing.expectError(2507 try std.testing.expectError(
2505 error.ParseZon,2508 error.ParseZon,
2506 fromSlice([4:0]u8, .{2509 fromSliceNoAlloc([4:0]u8, .{
2507 .gpa = gpa,2510 .gpa = gpa,
2511 .arena = arena,
2508 .source = "\"abcd\"",2512 .source = "\"abcd\"",
2509 .errors = &errors,2513 .errors = &errors,
2510 }),2514 }),
2511 );2515 );
2512 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});2516 try std.testing.expectFmt(
2517 \\input.zon: error.ParseZon
2518 \\input.zon:1:1: error: expected array
2519 \\
2520 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2513 }2521 }
25142522
2515 {2523 {
2516 var errors: Errors = .init(arena);
2517 try std.testing.expectError(2524 try std.testing.expectError(
2518 error.ParseZon,2525 error.ParseZon,
2519 fromSlice([4:0]u8, .{2526 fromSliceNoAlloc([4:0]u8, .{
2520 .gpa = gpa,2527 .gpa = gpa,
2528 .arena = arena,
2521 .source = "\\\\abcd",2529 .source = "\\\\abcd",
2522 .errors = &errors,2530 .errors = &errors,
2523 }),2531 }),
2524 );2532 );
2525 try std.testing.expectFmt(2533 try std.testing.expectFmt(
2534 \\input.zon: error.ParseZon
2526 \\input.zon:1:1: error: expected array2535 \\input.zon:1:1: error: expected array
2527 \\2536 \\
2528 , "{f}", .{errors.fmt("input.zon")});2537 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2529 }2538 }
2530 }2539 }
25312540
2532 // Zero terminated slices2541 // Zero terminated slices
2533 {2542 {
2534 {2543 {
2535 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{2544 const parsed: [:0]const u8 = try fromSlice([:0]const u8, .{
2536 .gpa = gpa,2545 .gpa = gpa,
2537 .arena = arena,2546 .arena = arena,
2538 .source = "\"abc\"",2547 .source = "\"abc\"",
2539 .errors = null,2548 .errors = &errors,
2540 });2549 });
2541 try std.testing.expectEqualStrings("abc", parsed);2550 try std.testing.expectEqualStrings("abc", parsed);
2542 try std.testing.expectEqual(@as(u8, 0), parsed[3]);2551 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
2543 }2552 }
25442553
2545 {2554 {
2546 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{2555 const parsed: [:0]const u8 = try fromSlice([:0]const u8, .{
2547 .gpa = gpa,2556 .gpa = gpa,
2548 .arena = arena,2557 .arena = arena,
2549 .source = "\\\\abc",2558 .source = "\\\\abc",
2550 .errors = null,2559 .errors = &errors,
2551 });2560 });
2552 try std.testing.expectEqualStrings("abc", parsed);2561 try std.testing.expectEqualStrings("abc", parsed);
2553 try std.testing.expectEqual(@as(u8, 0), parsed[3]);2562 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
...@@ -2557,114 +2566,119 @@ test "std.zon string literal" {...@@ -2557,114 +2566,119 @@ test "std.zon string literal" {
2557 // Other value terminated slices2566 // Other value terminated slices
2558 {2567 {
2559 {2568 {
2560 var errors: Errors = .init(arena);
2561 try std.testing.expectError(2569 try std.testing.expectError(
2562 error.ParseZon,2570 error.ParseZon,
2563 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\"foo\"", .errors = &errors }),2571 fromSlice([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\"foo\"", .errors = &errors }),
2564 );2572 );
2565 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});2573 try std.testing.expectFmt(
2574 \\input.zon: error.ParseZon
2575 \\input.zon:1:1: error: expected array
2576 \\
2577 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2566 }2578 }
25672579
2568 {2580 {
2569 var errors: Errors = .init(arena);
2570 try std.testing.expectError(2581 try std.testing.expectError(
2571 error.ParseZon,2582 error.ParseZon,
2572 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\foo", .errors = &errors }),2583 fromSlice([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\foo", .errors = &errors }),
2573 );2584 );
2574 try std.testing.expectFmt(2585 try std.testing.expectFmt(
2586 \\input.zon: error.ParseZon
2575 \\input.zon:1:1: error: expected array2587 \\input.zon:1:1: error: expected array
2576 \\2588 \\
2577 , "{f}", .{errors.fmt("input.zon")});2589 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2578 }2590 }
2579 }2591 }
25802592
2581 // Expecting string literal, getting something else2593 // Expecting string literal, getting something else
2582 {2594 {
2583 var errors: Errors = .init(arena);
2584 try std.testing.expectError(2595 try std.testing.expectError(
2585 error.ParseZon,2596 error.ParseZon,
2586 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = "true", .errors = &errors }),2597 fromSlice([]const u8, .{ .gpa = gpa, .arena = arena, .source = "true", .errors = &errors }),
2587 );2598 );
2588 try std.testing.expectFmt(2599 try std.testing.expectFmt(
2600 \\input.zon: error.ParseZon
2589 \\input.zon:1:1: error: expected string2601 \\input.zon:1:1: error: expected string
2590 \\2602 \\
2591 , "{f}", .{errors.fmt("input.zon")});2603 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2592 }2604 }
25932605
2594 // Expecting string literal, getting an incompatible tuple2606 // Expecting string literal, getting an incompatible tuple
2595 {2607 {
2596 var errors: Errors = .init(arena);
2597 try std.testing.expectError(2608 try std.testing.expectError(
2598 error.ParseZon,2609 error.ParseZon,
2599 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = ".{false}", .errors = &errors }),2610 fromSlice([]const u8, .{ .gpa = gpa, .arena = arena, .source = ".{false}", .errors = &errors }),
2600 );2611 );
2601 try std.testing.expectFmt(2612 try std.testing.expectFmt(
2613 \\input.zon: error.ParseZon
2602 \\input.zon:1:3: error: expected type 'u8'2614 \\input.zon:1:3: error: expected type 'u8'
2603 \\2615 \\
2604 , "{f}", .{errors.fmt("input.zon")});2616 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2605 }2617 }
26062618
2607 // Invalid string literal2619 // Invalid string literal
2608 {2620 {
2609 var errors: Errors = .init(arena);
2610 try std.testing.expectError(2621 try std.testing.expectError(
2611 error.ParseZon,2622 error.ParseZon,
2612 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"\\a\"", .errors = &errors }),2623 fromSlice([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"\\a\"", .errors = &errors }),
2613 );2624 );
2614 try std.testing.expectFmt(2625 try std.testing.expectFmt(
2626 \\input.zon: error.ParseZon
2615 \\input.zon:1:3: error: invalid escape character: 'a'2627 \\input.zon:1:3: error: invalid escape character: 'a'
2616 \\2628 \\
2617 , "{f}", .{errors.fmt("input.zon")});2629 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2618 }2630 }
26192631
2620 // Slice wrong child type2632 // Slice wrong child type
2621 {2633 {
2622 {2634 {
2623 var errors: Errors = .init(arena);
2624 try std.testing.expectError(2635 try std.testing.expectError(
2625 error.ParseZon,2636 error.ParseZon,
2626 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"a\"", .errors = &errors }),2637 fromSlice([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"a\"", .errors = &errors }),
2627 );2638 );
2628 try std.testing.expectFmt(2639 try std.testing.expectFmt(
2640 \\input.zon: error.ParseZon
2629 \\input.zon:1:1: error: expected array2641 \\input.zon:1:1: error: expected array
2630 \\2642 \\
2631 , "{f}", .{errors.fmt("input.zon")});2643 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2632 }2644 }
26332645
2634 {2646 {
2635 var errors: Errors = .init(arena);
2636 try std.testing.expectError(2647 try std.testing.expectError(
2637 error.ParseZon,2648 error.ParseZon,
2638 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\\\\a", .errors = &errors }),2649 fromSlice([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\\\\a", .errors = &errors }),
2639 );2650 );
2640 try std.testing.expectFmt(2651 try std.testing.expectFmt(
2652 \\input.zon: error.ParseZon
2641 \\input.zon:1:1: error: expected array2653 \\input.zon:1:1: error: expected array
2642 \\2654 \\
2643 , "{f}", .{errors.fmt("input.zon")});2655 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2644 }2656 }
2645 }2657 }
26462658
2647 // Bad alignment2659 // Bad alignment
2648 {2660 {
2649 {2661 {
2650 var errors: Errors = .init(arena);
2651 try std.testing.expectError(2662 try std.testing.expectError(
2652 error.ParseZon,2663 error.ParseZon,
2653 fromSliceAlloc([]align(2) const u8, .{2664 fromSlice([]align(2) const u8, .{
2654 .gpa = gpa,2665 .gpa = gpa,
2655 .arena = arena,2666 .arena = arena,
2656 .source = "\"abc\"",2667 .source = "\"abc\"",
2657 .errors = &errors,2668 .errors = &errors,
2658 }),2669 }),
2659 );2670 );
2660 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});2671 try std.testing.expectFmt(
2672 \\input.zon: error.ParseZon
2673 \\input.zon:1:1: error: expected array
2674 \\
2675 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2661 }2676 }
26622677
2663 {2678 {
2664 var errors: Errors = .init(arena);
2665 try std.testing.expectError(2679 try std.testing.expectError(
2666 error.ParseZon,2680 error.ParseZon,
2667 fromSliceAlloc([]align(2) const u8, .{2681 fromSlice([]align(2) const u8, .{
2668 .gpa = gpa,2682 .gpa = gpa,
2669 .arena = arena,2683 .arena = arena,
2670 .source = "\\\\abc",2684 .source = "\\\\abc",
...@@ -2672,9 +2686,10 @@ test "std.zon string literal" {...@@ -2672,9 +2686,10 @@ test "std.zon string literal" {
2672 }),2686 }),
2673 );2687 );
2674 try std.testing.expectFmt(2688 try std.testing.expectFmt(
2689 \\input.zon: error.ParseZon
2675 \\input.zon:1:1: error: expected array2690 \\input.zon:1:1: error: expected array
2676 \\2691 \\
2677 , "{f}", .{errors.fmt("input.zon")});2692 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2678 }2693 }
2679 }2694 }
26802695
...@@ -2687,7 +2702,7 @@ test "std.zon string literal" {...@@ -2687,7 +2702,7 @@ test "std.zon string literal" {
2687 message2: String,2702 message2: String,
2688 message3: String,2703 message3: String,
2689 };2704 };
2690 const parsed = try fromSliceAlloc(S, .{2705 const parsed = try fromSlice(S, .{
2691 .gpa = gpa,2706 .gpa = gpa,
2692 .arena = arena,2707 .arena = arena,
2693 .source =2708 .source =
...@@ -2708,7 +2723,7 @@ test "std.zon string literal" {...@@ -2708,7 +2723,7 @@ test "std.zon string literal" {
2708 \\ \\and this.2723 \\ \\and this.
2709 \\}2724 \\}
2710 ,2725 ,
2711 .errors = null,2726 .errors = &errors,
2712 });2727 });
2713 try std.testing.expectEqualStrings(2728 try std.testing.expectEqualStrings(
2714 "hello, world!\nthis is a multiline string!\n\n...",2729 "hello, world!\nthis is a multiline string!\n\n...",
...@@ -2725,6 +2740,7 @@ test "std.zon enum literals" {...@@ -2725,6 +2740,7 @@ test "std.zon enum literals" {
2725 var arena_allocator: ArenaAllocator = .init(gpa);2740 var arena_allocator: ArenaAllocator = .init(gpa);
2726 defer arena_allocator.deinit();2741 defer arena_allocator.deinit();
2727 const arena = arena_allocator.allocator();2742 const arena = arena_allocator.allocator();
2743 var errors: Errors = .empty;
27282744
2729 const Enum = enum {2745 const Enum = enum {
2730 foo,2746 foo,
...@@ -2734,98 +2750,106 @@ test "std.zon enum literals" {...@@ -2734,98 +2750,106 @@ test "std.zon enum literals" {
2734 };2750 };
27352751
2736 // Tags that exist2752 // Tags that exist
2737 try std.testing.expectEqual(Enum.foo, try fromSlice(Enum, .{2753 try std.testing.expectEqual(Enum.foo, try fromSliceNoAlloc(Enum, .{
2738 .gpa = gpa,2754 .gpa = gpa,
2755 .arena = arena,
2739 .source = ".foo",2756 .source = ".foo",
2740 .errors = null,2757 .errors = &errors,
2741 }));2758 }));
2742 try std.testing.expectEqual(Enum.bar, try fromSlice(Enum, .{2759 try std.testing.expectEqual(Enum.bar, try fromSliceNoAlloc(Enum, .{
2743 .gpa = gpa,2760 .gpa = gpa,
2761 .arena = arena,
2744 .source = ".bar",2762 .source = ".bar",
2745 .errors = null,2763 .errors = &errors,
2746 }));2764 }));
2747 try std.testing.expectEqual(Enum.baz, try fromSlice(Enum, .{2765 try std.testing.expectEqual(Enum.baz, try fromSliceNoAlloc(Enum, .{
2748 .gpa = gpa,2766 .gpa = gpa,
2767 .arena = arena,
2749 .source = ".baz",2768 .source = ".baz",
2750 .errors = null,2769 .errors = &errors,
2751 }));2770 }));
2752 try std.testing.expectEqual(2771 try std.testing.expectEqual(
2753 Enum.@"ab\nc",2772 Enum.@"ab\nc",
2754 try fromSlice(Enum, .{2773 try fromSliceNoAlloc(Enum, .{
2755 .gpa = gpa,2774 .gpa = gpa,
2775 .arena = arena,
2756 .source = ".@\"ab\\nc\"",2776 .source = ".@\"ab\\nc\"",
2757 .errors = null,2777 .errors = &errors,
2758 }),2778 }),
2759 );2779 );
27602780
2761 // Bad tag2781 // Bad tag
2762 {2782 {
2763 var errors: Errors = .init(arena);
2764 try std.testing.expectError(2783 try std.testing.expectError(
2765 error.ParseZon,2784 error.ParseZon,
2766 fromSlice(Enum, .{2785 fromSliceNoAlloc(Enum, .{
2767 .gpa = gpa,2786 .gpa = gpa,
2787 .arena = arena,
2768 .source = ".qux",2788 .source = ".qux",
2769 .errors = &errors,2789 .errors = &errors,
2770 }),2790 }),
2771 );2791 );
2772 try std.testing.expectFmt(2792 try std.testing.expectFmt(
2793 \\input.zon: error.ParseZon
2773 \\input.zon:1:2: error: unexpected enum literal 'qux'2794 \\input.zon:1:2: error: unexpected enum literal 'qux'
2774 \\input.zon:1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2795 \\input.zon:1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2775 \\2796 \\
2776 , "{f}", .{errors.fmt("input.zon")});2797 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2777 }2798 }
27782799
2779 // Bad tag that's too long for parser2800 // Bad tag that's too long for parser
2780 {2801 {
2781 var errors: Errors = .init(arena);
2782 try std.testing.expectError(2802 try std.testing.expectError(
2783 error.ParseZon,2803 error.ParseZon,
2784 fromSlice(Enum, .{2804 fromSliceNoAlloc(Enum, .{
2785 .gpa = gpa,2805 .gpa = gpa,
2806 .arena = arena,
2786 .source = ".@\"foobarbaz\"",2807 .source = ".@\"foobarbaz\"",
2787 .errors = &errors,2808 .errors = &errors,
2788 }),2809 }),
2789 );2810 );
2790 try std.testing.expectFmt(2811 try std.testing.expectFmt(
2812 \\input.zon: error.ParseZon
2791 \\input.zon:1:2: error: unexpected enum literal 'foobarbaz'2813 \\input.zon:1:2: error: unexpected enum literal 'foobarbaz'
2792 \\input.zon:1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2814 \\input.zon:1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2793 \\2815 \\
2794 , "{f}", .{errors.fmt("input.zon")});2816 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2795 }2817 }
27962818
2797 // Bad type2819 // Bad type
2798 {2820 {
2799 var errors: Errors = .init(arena);
2800 try std.testing.expectError(2821 try std.testing.expectError(
2801 error.ParseZon,2822 error.ParseZon,
2802 fromSlice(Enum, .{2823 fromSliceNoAlloc(Enum, .{
2803 .gpa = gpa,2824 .gpa = gpa,
2825 .arena = arena,
2804 .source = "true",2826 .source = "true",
2805 .errors = &errors,2827 .errors = &errors,
2806 }),2828 }),
2807 );2829 );
2808 try std.testing.expectFmt(2830 try std.testing.expectFmt(
2831 \\input.zon: error.ParseZon
2809 \\input.zon:1:1: error: expected enum literal2832 \\input.zon:1:1: error: expected enum literal
2810 \\2833 \\
2811 , "{f}", .{errors.fmt("input.zon")});2834 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2812 }2835 }
28132836
2814 // Test embedded nulls in an identifier2837 // Test embedded nulls in an identifier
2815 {2838 {
2816 var errors: Errors = .init(arena);
2817 try std.testing.expectError(2839 try std.testing.expectError(
2818 error.ParseZon,2840 error.ParseZon,
2819 fromSlice(Enum, .{2841 fromSliceNoAlloc(Enum, .{
2820 .gpa = gpa,2842 .gpa = gpa,
2843 .arena = arena,
2821 .source = ".@\"\\x00\"",2844 .source = ".@\"\\x00\"",
2822 .errors = &errors,2845 .errors = &errors,
2823 }),2846 }),
2824 );2847 );
2825 try std.testing.expectFmt(2848 try std.testing.expectFmt(
2849 \\input.zon: error.ParseZon
2826 \\input.zon:1:2: error: identifier cannot contain null bytes2850 \\input.zon:1:2: error: identifier cannot contain null bytes
2827 \\2851 \\
2828 , "{f}", .{errors.fmt("input.zon")});2852 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2829 }2853 }
2830}2854}
28312855
...@@ -2834,48 +2858,53 @@ test "std.zon parse bool" {...@@ -2834,48 +2858,53 @@ test "std.zon parse bool" {
2834 var arena_allocator: ArenaAllocator = .init(gpa);2858 var arena_allocator: ArenaAllocator = .init(gpa);
2835 defer arena_allocator.deinit();2859 defer arena_allocator.deinit();
2836 const arena = arena_allocator.allocator();2860 const arena = arena_allocator.allocator();
2861 var errors: Errors = .empty;
28372862
2838 // Correct bools2863 // Correct bools
2839 try std.testing.expectEqual(true, try fromSlice(bool, .{2864 try std.testing.expectEqual(true, try fromSliceNoAlloc(bool, .{
2840 .gpa = gpa,2865 .gpa = gpa,
2866 .arena = arena,
2841 .source = "true",2867 .source = "true",
2842 .errors = null,2868 .errors = &errors,
2843 }));2869 }));
2844 try std.testing.expectEqual(false, try fromSlice(bool, .{2870 try std.testing.expectEqual(false, try fromSliceNoAlloc(bool, .{
2845 .gpa = gpa,2871 .gpa = gpa,
2872 .arena = arena,
2846 .source = "false",2873 .source = "false",
2847 .errors = null,2874 .errors = &errors,
2848 }));2875 }));
28492876
2850 // Errors2877 // Errors
2851 {2878 {
2852 var errors: Errors = .init(arena);
2853 try std.testing.expectError(2879 try std.testing.expectError(
2854 error.ParseZon,2880 error.ParseZon,
2855 fromSlice(bool, .{2881 fromSliceNoAlloc(bool, .{
2856 .gpa = gpa,2882 .gpa = gpa,
2883 .arena = arena,
2857 .source = " foo",2884 .source = " foo",
2858 .errors = &errors,2885 .errors = &errors,
2859 }),2886 }),
2860 );2887 );
2861 try std.testing.expectFmt(2888 try std.testing.expectFmt(
2889 \\input.zon: error.ParseZon
2862 \\input.zon:1:2: error: invalid expression2890 \\input.zon:1:2: error: invalid expression
2863 \\input.zon:1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'2891 \\input.zon:1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
2864 \\input.zon:1:2: note: precede identifier with '.' for an enum literal2892 \\input.zon:1:2: note: precede identifier with '.' for an enum literal
2865 \\2893 \\
2866 , "{f}", .{errors.fmt("input.zon")});2894 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2867 }2895 }
2868 {2896 {
2869 var errors: Errors = .init(arena);2897 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(bool, .{
2870 try std.testing.expectError(error.ParseZon, fromSlice(bool, .{
2871 .gpa = gpa,2898 .gpa = gpa,
2899 .arena = arena,
2872 .source = "123",2900 .source = "123",
2873 .errors = &errors,2901 .errors = &errors,
2874 }));2902 }));
2875 try std.testing.expectFmt(2903 try std.testing.expectFmt(
2904 \\input.zon: error.ParseZon
2876 \\input.zon:1:1: error: expected type 'bool'2905 \\input.zon:1:1: error: expected type 'bool'
2877 \\2906 \\
2878 , "{f}", .{errors.fmt("input.zon")});2907 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
2879 }2908 }
2880}2909}
28812910
...@@ -2906,410 +2935,461 @@ test "std.zon parse int" {...@@ -2906,410 +2935,461 @@ test "std.zon parse int" {
2906 var arena_allocator: ArenaAllocator = .init(gpa);2935 var arena_allocator: ArenaAllocator = .init(gpa);
2907 defer arena_allocator.deinit();2936 defer arena_allocator.deinit();
2908 const arena = arena_allocator.allocator();2937 const arena = arena_allocator.allocator();
2938 var errors: Errors = .empty;
29092939
2910 // Test various numbers and types2940 // Test various numbers and types
2911 try std.testing.expectEqual(@as(u8, 10), try fromSlice(u8, .{2941 try std.testing.expectEqual(@as(u8, 10), try fromSliceNoAlloc(u8, .{
2912 .gpa = gpa,2942 .gpa = gpa,
2943 .arena = arena,
2913 .source = "10",2944 .source = "10",
2914 .errors = null,2945 .errors = &errors,
2915 }));2946 }));
2916 try std.testing.expectEqual(@as(i16, 24), try fromSlice(i16, .{2947 try std.testing.expectEqual(@as(i16, 24), try fromSliceNoAlloc(i16, .{
2917 .gpa = gpa,2948 .gpa = gpa,
2949 .arena = arena,
2918 .source = "24",2950 .source = "24",
2919 .errors = null,2951 .errors = &errors,
2920 }));2952 }));
2921 try std.testing.expectEqual(@as(i14, -4), try fromSlice(i14, .{2953 try std.testing.expectEqual(@as(i14, -4), try fromSliceNoAlloc(i14, .{
2922 .gpa = gpa,2954 .gpa = gpa,
2955 .arena = arena,
2923 .source = "-4",2956 .source = "-4",
2924 .errors = null,2957 .errors = &errors,
2925 }));2958 }));
2926 try std.testing.expectEqual(@as(i32, -123), try fromSlice(i32, .{2959 try std.testing.expectEqual(@as(i32, -123), try fromSliceNoAlloc(i32, .{
2927 .gpa = gpa,2960 .gpa = gpa,
2961 .arena = arena,
2928 .source = "-123",2962 .source = "-123",
2929 .errors = null,2963 .errors = &errors,
2930 }));2964 }));
29312965
2932 // Test limits2966 // Test limits
2933 try std.testing.expectEqual(@as(i8, 127), try fromSlice(i8, .{2967 try std.testing.expectEqual(@as(i8, 127), try fromSliceNoAlloc(i8, .{
2934 .gpa = gpa,2968 .gpa = gpa,
2969 .arena = arena,
2935 .source = "127",2970 .source = "127",
2936 .errors = null,2971 .errors = &errors,
2937 }));2972 }));
2938 try std.testing.expectEqual(@as(i8, -128), try fromSlice(i8, .{2973 try std.testing.expectEqual(@as(i8, -128), try fromSliceNoAlloc(i8, .{
2939 .gpa = gpa,2974 .gpa = gpa,
2975 .arena = arena,
2940 .source = "-128",2976 .source = "-128",
2941 .errors = null,2977 .errors = &errors,
2942 }));2978 }));
29432979
2944 // Test characters2980 // Test characters
2945 try std.testing.expectEqual(@as(u8, 'a'), try fromSlice(u8, .{2981 try std.testing.expectEqual(@as(u8, 'a'), try fromSliceNoAlloc(u8, .{
2946 .gpa = gpa,2982 .gpa = gpa,
2983 .arena = arena,
2947 .source = "'a'",2984 .source = "'a'",
2948 .errors = null,2985 .errors = &errors,
2949 }));2986 }));
2950 try std.testing.expectEqual(@as(u8, 'z'), try fromSlice(u8, .{2987 try std.testing.expectEqual(@as(u8, 'z'), try fromSliceNoAlloc(u8, .{
2951 .gpa = gpa,2988 .gpa = gpa,
2989 .arena = arena,
2952 .source = "'z'",2990 .source = "'z'",
2953 .errors = null,2991 .errors = &errors,
2954 }));2992 }));
29552993
2956 // Test big integers2994 // Test big integers
2957 try std.testing.expectEqual(2995 try std.testing.expectEqual(
2958 @as(u65, 36893488147419103231),2996 @as(u65, 36893488147419103231),
2959 try fromSlice(u65, .{2997 try fromSliceNoAlloc(u65, .{
2960 .gpa = gpa,2998 .gpa = gpa,
2999 .arena = arena,
2961 .source = "36893488147419103231",3000 .source = "36893488147419103231",
2962 .errors = null,3001 .errors = &errors,
2963 }),3002 }),
2964 );3003 );
2965 try std.testing.expectEqual(3004 try std.testing.expectEqual(
2966 @as(u65, 36893488147419103231),3005 @as(u65, 36893488147419103231),
2967 try fromSlice(u65, .{3006 try fromSliceNoAlloc(u65, .{
2968 .gpa = gpa,3007 .gpa = gpa,
3008 .arena = arena,
2969 .source = "368934_881_474191032_31",3009 .source = "368934_881_474191032_31",
2970 .errors = null,3010 .errors = &errors,
2971 }),3011 }),
2972 );3012 );
2973 try std.testing.expectEqual(3013 try std.testing.expectEqual(
2974 @as(u128, 340282366920938463463374607431768211455),3014 @as(u128, 340282366920938463463374607431768211455),
2975 try fromSlice(u128, .{3015 try fromSliceNoAlloc(u128, .{
2976 .gpa = gpa,3016 .gpa = gpa,
3017 .arena = arena,
2977 .source = "340282366920938463463374607431768211455",3018 .source = "340282366920938463463374607431768211455",
2978 .errors = null,3019 .errors = &errors,
2979 }),3020 }),
2980 );3021 );
29813022
2982 // Test big integer limits3023 // Test big integer limits
2983 try std.testing.expectEqual(3024 try std.testing.expectEqual(
2984 @as(i66, 36893488147419103231),3025 @as(i66, 36893488147419103231),
2985 try fromSlice(i66, .{3026 try fromSliceNoAlloc(i66, .{
2986 .gpa = gpa,3027 .gpa = gpa,
3028 .arena = arena,
2987 .source = "36893488147419103231",3029 .source = "36893488147419103231",
2988 .errors = null,3030 .errors = &errors,
2989 }),3031 }),
2990 );3032 );
2991 try std.testing.expectEqual(3033 try std.testing.expectEqual(
2992 @as(i66, -36893488147419103232),3034 @as(i66, -36893488147419103232),
2993 try fromSlice(i66, .{3035 try fromSliceNoAlloc(i66, .{
2994 .gpa = gpa,3036 .gpa = gpa,
3037 .arena = arena,
2995 .source = "-36893488147419103232",3038 .source = "-36893488147419103232",
2996 .errors = null,3039 .errors = &errors,
2997 }),3040 }),
2998 );3041 );
2999 {3042 {
3000 var errors: Errors = .init(arena);3043 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i66, .{
3001 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
3002 .gpa = gpa,3044 .gpa = gpa,
3045 .arena = arena,
3003 .source = "36893488147419103232",3046 .source = "36893488147419103232",
3004 .errors = &errors,3047 .errors = &errors,
3005 }));3048 }));
3006 try std.testing.expectFmt(3049 try std.testing.expectFmt(
3050 \\input.zon: error.ParseZon
3007 \\input.zon:1:1: error: type 'i66' cannot represent value3051 \\input.zon:1:1: error: type 'i66' cannot represent value
3008 \\3052 \\
3009 , "{f}", .{errors.fmt("input.zon")});3053 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3010 }3054 }
3011 {3055 {
3012 var errors: Errors = .init(arena);3056 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i66, .{
3013 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
3014 .gpa = gpa,3057 .gpa = gpa,
3058 .arena = arena,
3015 .source = "-36893488147419103233",3059 .source = "-36893488147419103233",
3016 .errors = &errors,3060 .errors = &errors,
3017 }));3061 }));
3018 try std.testing.expectFmt(3062 try std.testing.expectFmt(
3063 \\input.zon: error.ParseZon
3019 \\input.zon:1:1: error: type 'i66' cannot represent value3064 \\input.zon:1:1: error: type 'i66' cannot represent value
3020 \\3065 \\
3021 , "{f}", .{errors.fmt("input.zon")});3066 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3022 }3067 }
30233068
3024 // Test parsing whole number floats as integers3069 // Test parsing whole number floats as integers
3025 try std.testing.expectEqual(@as(i8, -1), try fromSlice(i8, .{3070 try std.testing.expectEqual(@as(i8, -1), try fromSliceNoAlloc(i8, .{
3026 .gpa = gpa,3071 .gpa = gpa,
3072 .arena = arena,
3027 .source = "-1.0",3073 .source = "-1.0",
3028 .errors = null,3074 .errors = &errors,
3029 }));3075 }));
3030 try std.testing.expectEqual(@as(i8, 123), try fromSlice(i8, .{3076 try std.testing.expectEqual(@as(i8, 123), try fromSliceNoAlloc(i8, .{
3031 .gpa = gpa,3077 .gpa = gpa,
3078 .arena = arena,
3032 .source = "123.0",3079 .source = "123.0",
3033 .errors = null,3080 .errors = &errors,
3034 }));3081 }));
30353082
3036 // Test non-decimal integers3083 // Test non-decimal integers
3037 try std.testing.expectEqual(@as(i16, 0xff), try fromSlice(i16, .{3084 try std.testing.expectEqual(@as(i16, 0xff), try fromSliceNoAlloc(i16, .{
3038 .gpa = gpa,3085 .gpa = gpa,
3086 .arena = arena,
3039 .source = "0xff",3087 .source = "0xff",
3040 .errors = null,3088 .errors = &errors,
3041 }));3089 }));
3042 try std.testing.expectEqual(@as(i16, -0xff), try fromSlice(i16, .{3090 try std.testing.expectEqual(@as(i16, -0xff), try fromSliceNoAlloc(i16, .{
3043 .gpa = gpa,3091 .gpa = gpa,
3092 .arena = arena,
3044 .source = "-0xff",3093 .source = "-0xff",
3045 .errors = null,3094 .errors = &errors,
3046 }));3095 }));
3047 try std.testing.expectEqual(@as(i16, 0o77), try fromSlice(i16, .{3096 try std.testing.expectEqual(@as(i16, 0o77), try fromSliceNoAlloc(i16, .{
3048 .gpa = gpa,3097 .gpa = gpa,
3098 .arena = arena,
3049 .source = "0o77",3099 .source = "0o77",
3050 .errors = null,3100 .errors = &errors,
3051 }));3101 }));
3052 try std.testing.expectEqual(@as(i16, -0o77), try fromSlice(i16, .{3102 try std.testing.expectEqual(@as(i16, -0o77), try fromSliceNoAlloc(i16, .{
3053 .gpa = gpa,3103 .gpa = gpa,
3104 .arena = arena,
3054 .source = "-0o77",3105 .source = "-0o77",
3055 .errors = null,3106 .errors = &errors,
3056 }));3107 }));
3057 try std.testing.expectEqual(@as(i16, 0b11), try fromSlice(i16, .{3108 try std.testing.expectEqual(@as(i16, 0b11), try fromSliceNoAlloc(i16, .{
3058 .gpa = gpa,3109 .gpa = gpa,
3110 .arena = arena,
3059 .source = "0b11",3111 .source = "0b11",
3060 .errors = null,3112 .errors = &errors,
3061 }));3113 }));
3062 try std.testing.expectEqual(@as(i16, -0b11), try fromSlice(i16, .{3114 try std.testing.expectEqual(@as(i16, -0b11), try fromSliceNoAlloc(i16, .{
3063 .gpa = gpa,3115 .gpa = gpa,
3116 .arena = arena,
3064 .source = "-0b11",3117 .source = "-0b11",
3065 .errors = null,3118 .errors = &errors,
3066 }));3119 }));
30673120
3068 // Test non-decimal big integers3121 // Test non-decimal big integers
3069 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(u65, .{3122 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSliceNoAlloc(u65, .{
3070 .gpa = gpa,3123 .gpa = gpa,
3124 .arena = arena,
3071 .source = "0x1ffffffffffffffff",3125 .source = "0x1ffffffffffffffff",
3072 .errors = null,3126 .errors = &errors,
3073 }));3127 }));
3074 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(i66, .{3128 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSliceNoAlloc(i66, .{
3075 .gpa = gpa,3129 .gpa = gpa,
3130 .arena = arena,
3076 .source = "0x1ffffffffffffffff",3131 .source = "0x1ffffffffffffffff",
3077 .errors = null,3132 .errors = &errors,
3078 }));3133 }));
3079 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(i66, .{3134 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSliceNoAlloc(i66, .{
3080 .gpa = gpa,3135 .gpa = gpa,
3136 .arena = arena,
3081 .source = "-0x1ffffffffffffffff",3137 .source = "-0x1ffffffffffffffff",
3082 .errors = null,3138 .errors = &errors,
3083 }));3139 }));
3084 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(u65, .{3140 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSliceNoAlloc(u65, .{
3085 .gpa = gpa,3141 .gpa = gpa,
3142 .arena = arena,
3086 .source = "0o3777777777777777777777",3143 .source = "0o3777777777777777777777",
3087 .errors = null,3144 .errors = &errors,
3088 }));3145 }));
3089 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(i66, .{3146 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSliceNoAlloc(i66, .{
3090 .gpa = gpa,3147 .gpa = gpa,
3148 .arena = arena,
3091 .source = "0o3777777777777777777777",3149 .source = "0o3777777777777777777777",
3092 .errors = null,3150 .errors = &errors,
3093 }));3151 }));
3094 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(i66, .{3152 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSliceNoAlloc(i66, .{
3095 .gpa = gpa,3153 .gpa = gpa,
3154 .arena = arena,
3096 .source = "-0o3777777777777777777777",3155 .source = "-0o3777777777777777777777",
3097 .errors = null,3156 .errors = &errors,
3098 }));3157 }));
3099 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSlice(u65, .{3158 try std.testing.expectEqual(@as(u65, 0x1ffffffffffffffff), try fromSliceNoAlloc(u65, .{
3100 .gpa = gpa,3159 .gpa = gpa,
3160 .arena = arena,
3101 .source = "0b11111111111111111111111111111111111111111111111111111111111111111",3161 .source = "0b11111111111111111111111111111111111111111111111111111111111111111",
3102 .errors = null,3162 .errors = &errors,
3103 }));3163 }));
3104 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSlice(i66, .{3164 try std.testing.expectEqual(@as(i66, 0x1ffffffffffffffff), try fromSliceNoAlloc(i66, .{
3105 .gpa = gpa,3165 .gpa = gpa,
3166 .arena = arena,
3106 .source = "0b11111111111111111111111111111111111111111111111111111111111111111",3167 .source = "0b11111111111111111111111111111111111111111111111111111111111111111",
3107 .errors = null,3168 .errors = &errors,
3108 }));3169 }));
3109 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSlice(i66, .{3170 try std.testing.expectEqual(@as(i66, -0x1ffffffffffffffff), try fromSliceNoAlloc(i66, .{
3110 .gpa = gpa,3171 .gpa = gpa,
3172 .arena = arena,
3111 .source = "-0b11111111111111111111111111111111111111111111111111111111111111111",3173 .source = "-0b11111111111111111111111111111111111111111111111111111111111111111",
3112 .errors = null,3174 .errors = &errors,
3113 }));3175 }));
31143176
3115 // Number with invalid character in the middle3177 // Number with invalid character in the middle
3116 {3178 {
3117 var errors: Errors = .init(arena);3179 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3118 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3119 .gpa = gpa,3180 .gpa = gpa,
3181 .arena = arena,
3120 .source = "32a32",3182 .source = "32a32",
3121 .errors = &errors,3183 .errors = &errors,
3122 }));3184 }));
3123 try std.testing.expectFmt(3185 try std.testing.expectFmt(
3186 \\input.zon: error.ParseZon
3124 \\input.zon:1:3: error: invalid digit 'a' for decimal base3187 \\input.zon:1:3: error: invalid digit 'a' for decimal base
3125 \\3188 \\
3126 , "{f}", .{errors.fmt("input.zon")});3189 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3127 }3190 }
31283191
3129 // Failing to parse as int3192 // Failing to parse as int
3130 {3193 {
3131 var errors: Errors = .init(arena);3194 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3132 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3133 .gpa = gpa,3195 .gpa = gpa,
3196 .arena = arena,
3134 .source = "true",3197 .source = "true",
3135 .errors = &errors,3198 .errors = &errors,
3136 }));3199 }));
3137 try std.testing.expectFmt(3200 try std.testing.expectFmt(
3201 \\input.zon: error.ParseZon
3138 \\input.zon:1:1: error: expected type 'u8'3202 \\input.zon:1:1: error: expected type 'u8'
3139 \\3203 \\
3140 , "{f}", .{errors.fmt("input.zon")});3204 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3141 }3205 }
31423206
3143 // Failing because an int is out of range3207 // Failing because an int is out of range
3144 {3208 {
3145 var errors: Errors = .init(arena);3209 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3146 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3147 .gpa = gpa,3210 .gpa = gpa,
3211 .arena = arena,
3148 .source = "256",3212 .source = "256",
3149 .errors = &errors,3213 .errors = &errors,
3150 }));3214 }));
3151 try std.testing.expectFmt(3215 try std.testing.expectFmt(
3216 \\input.zon: error.ParseZon
3152 \\input.zon:1:1: error: type 'u8' cannot represent value3217 \\input.zon:1:1: error: type 'u8' cannot represent value
3153 \\3218 \\
3154 , "{f}", .{errors.fmt("input.zon")});3219 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3155 }3220 }
31563221
3157 // Failing because a negative int is out of range3222 // Failing because a negative int is out of range
3158 {3223 {
3159 var errors: Errors = .init(arena);3224 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3160 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3161 .gpa = gpa,3225 .gpa = gpa,
3226 .arena = arena,
3162 .source = "-129",3227 .source = "-129",
3163 .errors = &errors,3228 .errors = &errors,
3164 }));3229 }));
3165 try std.testing.expectFmt(3230 try std.testing.expectFmt(
3231 \\input.zon: error.ParseZon
3166 \\input.zon:1:1: error: type 'i8' cannot represent value3232 \\input.zon:1:1: error: type 'i8' cannot represent value
3167 \\3233 \\
3168 , "{f}", .{errors.fmt("input.zon")});3234 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3169 }3235 }
31703236
3171 // Failing because an unsigned int is negative3237 // Failing because an unsigned int is negative
3172 {3238 {
3173 var errors: Errors = .init(arena);3239 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3174 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3175 .gpa = gpa,3240 .gpa = gpa,
3241 .arena = arena,
3176 .source = "-1",3242 .source = "-1",
3177 .errors = &errors,3243 .errors = &errors,
3178 }));3244 }));
3179 try std.testing.expectFmt(3245 try std.testing.expectFmt(
3246 \\input.zon: error.ParseZon
3180 \\input.zon:1:1: error: type 'u8' cannot represent value3247 \\input.zon:1:1: error: type 'u8' cannot represent value
3181 \\3248 \\
3182 , "{f}", .{errors.fmt("input.zon")});3249 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3183 }3250 }
31843251
3185 // Failing because a float is non-whole3252 // Failing because a float is non-whole
3186 {3253 {
3187 var errors: Errors = .init(arena);3254 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3188 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3189 .gpa = gpa,3255 .gpa = gpa,
3256 .arena = arena,
3190 .source = "1.5",3257 .source = "1.5",
3191 .errors = &errors,3258 .errors = &errors,
3192 }));3259 }));
3193 try std.testing.expectFmt(3260 try std.testing.expectFmt(
3261 \\input.zon: error.ParseZon
3194 \\input.zon:1:1: error: type 'u8' cannot represent value3262 \\input.zon:1:1: error: type 'u8' cannot represent value
3195 \\3263 \\
3196 , "{f}", .{errors.fmt("input.zon")});3264 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3197 }3265 }
31983266
3199 // Failing because a float is negative3267 // Failing because a float is negative
3200 {3268 {
3201 var errors: Errors = .init(arena);3269 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3202 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3203 .gpa = gpa,3270 .gpa = gpa,
3271 .arena = arena,
3204 .source = "-1.0",3272 .source = "-1.0",
3205 .errors = &errors,3273 .errors = &errors,
3206 }));3274 }));
3207 try std.testing.expectFmt(3275 try std.testing.expectFmt(
3276 \\input.zon: error.ParseZon
3208 \\input.zon:1:1: error: type 'u8' cannot represent value3277 \\input.zon:1:1: error: type 'u8' cannot represent value
3209 \\3278 \\
3210 , "{f}", .{errors.fmt("input.zon")});3279 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3211 }3280 }
32123281
3213 // Negative integer zero3282 // Negative integer zero
3214 {3283 {
3215 var errors: Errors = .init(arena);3284 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3216 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3217 .gpa = gpa,3285 .gpa = gpa,
3286 .arena = arena,
3218 .source = "-0",3287 .source = "-0",
3219 .errors = &errors,3288 .errors = &errors,
3220 }));3289 }));
3221 try std.testing.expectFmt(3290 try std.testing.expectFmt(
3291 \\input.zon: error.ParseZon
3222 \\input.zon:1:2: error: integer literal '-0' is ambiguous3292 \\input.zon:1:2: error: integer literal '-0' is ambiguous
3223 \\input.zon:1:2: note: use '0' for an integer zero3293 \\input.zon:1:2: note: use '0' for an integer zero
3224 \\input.zon:1:2: note: use '-0.0' for a floating-point signed zero3294 \\input.zon:1:2: note: use '-0.0' for a floating-point signed zero
3225 \\3295 \\
3226 , "{f}", .{errors.fmt("input.zon")});3296 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3227 }3297 }
32283298
3229 // Negative integer zero casted to float3299 // Negative integer zero casted to float
3230 {3300 {
3231 var errors: Errors = .init(arena);3301 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(f32, .{
3232 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3233 .gpa = gpa,3302 .gpa = gpa,
3303 .arena = arena,
3234 .source = "-0",3304 .source = "-0",
3235 .errors = &errors,3305 .errors = &errors,
3236 }));3306 }));
3237 try std.testing.expectFmt(3307 try std.testing.expectFmt(
3308 \\input.zon: error.ParseZon
3238 \\input.zon:1:2: error: integer literal '-0' is ambiguous3309 \\input.zon:1:2: error: integer literal '-0' is ambiguous
3239 \\input.zon:1:2: note: use '0' for an integer zero3310 \\input.zon:1:2: note: use '0' for an integer zero
3240 \\input.zon:1:2: note: use '-0.0' for a floating-point signed zero3311 \\input.zon:1:2: note: use '-0.0' for a floating-point signed zero
3241 \\3312 \\
3242 , "{f}", .{errors.fmt("input.zon")});3313 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3243 }3314 }
32443315
3245 // Negative float 0 is allowed3316 // Negative float 0 is allowed
3246 try std.testing.expect(3317 try std.testing.expect(
3247 std.math.isNegativeZero(try fromSlice(f32, .{3318 std.math.isNegativeZero(try fromSliceNoAlloc(f32, .{
3248 .gpa = gpa,3319 .gpa = gpa,
3320 .arena = arena,
3249 .source = "-0.0",3321 .source = "-0.0",
3250 .errors = null,3322 .errors = &errors,
3251 })),3323 })),
3252 );3324 );
3253 try std.testing.expect(std.math.isPositiveZero(try fromSlice(f32, .{3325 try std.testing.expect(std.math.isPositiveZero(try fromSliceNoAlloc(f32, .{
3254 .gpa = gpa,3326 .gpa = gpa,
3327 .arena = arena,
3255 .source = "0.0",3328 .source = "0.0",
3256 .errors = null,3329 .errors = &errors,
3257 })));3330 })));
32583331
3259 // Double negation is not allowed3332 // Double negation is not allowed
3260 {3333 {
3261 var errors: Errors = .init(arena);3334 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3262 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3263 .gpa = gpa,3335 .gpa = gpa,
3336 .arena = arena,
3264 .source = "--2",3337 .source = "--2",
3265 .errors = &errors,3338 .errors = &errors,
3266 }));3339 }));
3267 try std.testing.expectFmt("input.zon:1:1: error: expected number or 'inf' after '-'\n", "{f}", .{errors.fmt("input.zon")});3340 try std.testing.expectFmt(
3341 \\input.zon: error.ParseZon
3342 \\input.zon:1:1: error: expected number or 'inf' after '-'
3343 \\
3344 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3268 }3345 }
32693346
3270 {3347 {
3271 var errors: Errors = .init(arena);
3272 try std.testing.expectError(3348 try std.testing.expectError(
3273 error.ParseZon,3349 error.ParseZon,
3274 fromSlice(f32, .{3350 fromSliceNoAlloc(f32, .{
3275 .gpa = gpa,3351 .gpa = gpa,
3352 .arena = arena,
3276 .source = "--2.0",3353 .source = "--2.0",
3277 .errors = &errors,3354 .errors = &errors,
3278 }),3355 }),
3279 );3356 );
3280 try std.testing.expectFmt(3357 try std.testing.expectFmt(
3358 \\input.zon: error.ParseZon
3281 \\input.zon:1:1: error: expected number or 'inf' after '-'3359 \\input.zon:1:1: error: expected number or 'inf' after '-'
3282 \\3360 \\
3283 , "{f}", .{errors.fmt("input.zon")});3361 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3284 }3362 }
32853363
3286 // Invalid int literal3364 // Invalid int literal
3287 {3365 {
3288 var errors: Errors = .init(arena);3366 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3289 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3290 .gpa = gpa,3367 .gpa = gpa,
3368 .arena = arena,
3291 .source = "0xg",3369 .source = "0xg",
3292 .errors = &errors,3370 .errors = &errors,
3293 }));3371 }));
3294 try std.testing.expectFmt(3372 try std.testing.expectFmt(
3373 \\input.zon: error.ParseZon
3295 \\input.zon:1:3: error: invalid digit 'g' for hex base3374 \\input.zon:1:3: error: invalid digit 'g' for hex base
3296 \\3375 \\
3297 , "{f}", .{errors.fmt("input.zon")});3376 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3298 }3377 }
32993378
3300 // Notes on invalid int literal3379 // Notes on invalid int literal
3301 {3380 {
3302 var errors: Errors = .init(arena);3381 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(u8, .{
3303 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
3304 .gpa = gpa,3382 .gpa = gpa,
3383 .arena = arena,
3305 .source = "0123",3384 .source = "0123",
3306 .errors = &errors,3385 .errors = &errors,
3307 }));3386 }));
3308 try std.testing.expectFmt(3387 try std.testing.expectFmt(
3388 \\input.zon: error.ParseZon
3309 \\input.zon:1:1: error: number '0123' has leading zero3389 \\input.zon:1:1: error: number '0123' has leading zero
3310 \\input.zon:1:1: note: use '0o' prefix for octal literals3390 \\input.zon:1:1: note: use '0o' prefix for octal literals
3311 \\3391 \\
3312 , "{f}", .{errors.fmt("input.zon")});3392 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3313 }3393 }
3314}3394}
33153395
...@@ -3318,30 +3398,33 @@ test "std.zon negative char" {...@@ -3318,30 +3398,33 @@ test "std.zon negative char" {
3318 var arena_allocator: ArenaAllocator = .init(gpa);3398 var arena_allocator: ArenaAllocator = .init(gpa);
3319 defer arena_allocator.deinit();3399 defer arena_allocator.deinit();
3320 const arena = arena_allocator.allocator();3400 const arena = arena_allocator.allocator();
3401 var errors: Errors = .empty;
33213402
3322 {3403 {
3323 var errors: Errors = .init(arena);3404 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(f32, .{
3324 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3325 .gpa = gpa,3405 .gpa = gpa,
3406 .arena = arena,
3326 .source = "-'a'",3407 .source = "-'a'",
3327 .errors = &errors,3408 .errors = &errors,
3328 }));3409 }));
3329 try std.testing.expectFmt(3410 try std.testing.expectFmt(
3411 \\input.zon: error.ParseZon
3330 \\input.zon:1:1: error: expected number or 'inf' after '-'3412 \\input.zon:1:1: error: expected number or 'inf' after '-'
3331 \\3413 \\
3332 , "{f}", .{errors.fmt("input.zon")});3414 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3333 }3415 }
3334 {3416 {
3335 var errors: Errors = .init(arena);3417 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i16, .{
3336 try std.testing.expectError(error.ParseZon, fromSlice(i16, .{
3337 .gpa = gpa,3418 .gpa = gpa,
3419 .arena = arena,
3338 .source = "-'a'",3420 .source = "-'a'",
3339 .errors = &errors,3421 .errors = &errors,
3340 }));3422 }));
3341 try std.testing.expectFmt(3423 try std.testing.expectFmt(
3424 \\input.zon: error.ParseZon
3342 \\input.zon:1:1: error: expected number or 'inf' after '-'3425 \\input.zon:1:1: error: expected number or 'inf' after '-'
3343 \\3426 \\
3344 , "{f}", .{errors.fmt("input.zon")});3427 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3345 }3428 }
3346}3429}
33473430
...@@ -3352,261 +3435,294 @@ test "std.zon parse float" {...@@ -3352,261 +3435,294 @@ test "std.zon parse float" {
3352 var arena_allocator: ArenaAllocator = .init(gpa);3435 var arena_allocator: ArenaAllocator = .init(gpa);
3353 defer arena_allocator.deinit();3436 defer arena_allocator.deinit();
3354 const arena = arena_allocator.allocator();3437 const arena = arena_allocator.allocator();
3438 var errors: Errors = .empty;
33553439
3356 // Test decimals3440 // Test decimals
3357 try std.testing.expectEqual(@as(f16, 0.5), try fromSlice(f16, .{3441 try std.testing.expectEqual(@as(f16, 0.5), try fromSliceNoAlloc(f16, .{
3358 .gpa = gpa,3442 .gpa = gpa,
3443 .arena = arena,
3359 .source = "0.5",3444 .source = "0.5",
3360 .errors = null,3445 .errors = &errors,
3361 }));3446 }));
3362 try std.testing.expectEqual(3447 try std.testing.expectEqual(
3363 @as(f32, 123.456),3448 @as(f32, 123.456),
3364 try fromSlice(f32, .{3449 try fromSliceNoAlloc(f32, .{
3365 .gpa = gpa,3450 .gpa = gpa,
3451 .arena = arena,
3366 .source = "123.456",3452 .source = "123.456",
3367 .errors = null,3453 .errors = &errors,
3368 }),3454 }),
3369 );3455 );
3370 try std.testing.expectEqual(3456 try std.testing.expectEqual(
3371 @as(f64, -123.456),3457 @as(f64, -123.456),
3372 try fromSlice(f64, .{3458 try fromSliceNoAlloc(f64, .{
3373 .gpa = gpa,3459 .gpa = gpa,
3460 .arena = arena,
3374 .source = "-123.456",3461 .source = "-123.456",
3375 .errors = null,3462 .errors = &errors,
3376 }),3463 }),
3377 );3464 );
3378 try std.testing.expectEqual(@as(f128, 42.5), try fromSlice(f128, .{3465 try std.testing.expectEqual(@as(f128, 42.5), try fromSliceNoAlloc(f128, .{
3379 .gpa = gpa,3466 .gpa = gpa,
3467 .arena = arena,
3380 .source = "42.5",3468 .source = "42.5",
3381 .errors = null,3469 .errors = &errors,
3382 }));3470 }));
33833471
3384 // Test whole numbers with and without decimals3472 // Test whole numbers with and without decimals
3385 try std.testing.expectEqual(@as(f16, 5.0), try fromSlice(f16, .{3473 try std.testing.expectEqual(@as(f16, 5.0), try fromSliceNoAlloc(f16, .{
3386 .gpa = gpa,3474 .gpa = gpa,
3475 .arena = arena,
3387 .source = "5.0",3476 .source = "5.0",
3388 .errors = null,3477 .errors = &errors,
3389 }));3478 }));
3390 try std.testing.expectEqual(@as(f16, 5.0), try fromSlice(f16, .{3479 try std.testing.expectEqual(@as(f16, 5.0), try fromSliceNoAlloc(f16, .{
3391 .gpa = gpa,3480 .gpa = gpa,
3481 .arena = arena,
3392 .source = "5",3482 .source = "5",
3393 .errors = null,3483 .errors = &errors,
3394 }));3484 }));
3395 try std.testing.expectEqual(@as(f32, -102), try fromSlice(f32, .{3485 try std.testing.expectEqual(@as(f32, -102), try fromSliceNoAlloc(f32, .{
3396 .gpa = gpa,3486 .gpa = gpa,
3487 .arena = arena,
3397 .source = "-102.0",3488 .source = "-102.0",
3398 .errors = null,3489 .errors = &errors,
3399 }));3490 }));
3400 try std.testing.expectEqual(@as(f32, -102), try fromSlice(f32, .{3491 try std.testing.expectEqual(@as(f32, -102), try fromSliceNoAlloc(f32, .{
3401 .gpa = gpa,3492 .gpa = gpa,
3493 .arena = arena,
3402 .source = "-102",3494 .source = "-102",
3403 .errors = null,3495 .errors = &errors,
3404 }));3496 }));
34053497
3406 // Test characters and negated characters3498 // Test characters and negated characters
3407 try std.testing.expectEqual(@as(f32, 'a'), try fromSlice(f32, .{3499 try std.testing.expectEqual(@as(f32, 'a'), try fromSliceNoAlloc(f32, .{
3408 .gpa = gpa,3500 .gpa = gpa,
3501 .arena = arena,
3409 .source = "'a'",3502 .source = "'a'",
3410 .errors = null,3503 .errors = &errors,
3411 }));3504 }));
3412 try std.testing.expectEqual(@as(f32, 'z'), try fromSlice(f32, .{3505 try std.testing.expectEqual(@as(f32, 'z'), try fromSliceNoAlloc(f32, .{
3413 .gpa = gpa,3506 .gpa = gpa,
3507 .arena = arena,
3414 .source = "'z'",3508 .source = "'z'",
3415 .errors = null,3509 .errors = &errors,
3416 }));3510 }));
34173511
3418 // Test big integers3512 // Test big integers
3419 try std.testing.expectEqual(3513 try std.testing.expectEqual(
3420 @as(f32, 36893488147419103231.0),3514 @as(f32, 36893488147419103231.0),
3421 try fromSlice(f32, .{3515 try fromSliceNoAlloc(f32, .{
3422 .gpa = gpa,3516 .gpa = gpa,
3517 .arena = arena,
3423 .source = "36893488147419103231",3518 .source = "36893488147419103231",
3424 .errors = null,3519 .errors = &errors,
3425 }),3520 }),
3426 );3521 );
3427 try std.testing.expectEqual(3522 try std.testing.expectEqual(
3428 @as(f32, -36893488147419103231.0),3523 @as(f32, -36893488147419103231.0),
3429 try fromSlice(f32, .{3524 try fromSliceNoAlloc(f32, .{
3430 .gpa = gpa,3525 .gpa = gpa,
3526 .arena = arena,
3431 .source = "-36893488147419103231",3527 .source = "-36893488147419103231",
3432 .errors = null,3528 .errors = &errors,
3433 }),3529 }),
3434 );3530 );
3435 try std.testing.expectEqual(@as(f128, 0x1ffffffffffffffff), try fromSlice(f128, .{3531 try std.testing.expectEqual(@as(f128, 0x1ffffffffffffffff), try fromSliceNoAlloc(f128, .{
3436 .gpa = gpa,3532 .gpa = gpa,
3533 .arena = arena,
3437 .source = "0x1ffffffffffffffff",3534 .source = "0x1ffffffffffffffff",
3438 .errors = null,3535 .errors = &errors,
3439 }));3536 }));
3440 try std.testing.expectEqual(@as(f32, @floatFromInt(0x1ffffffffffffffff)), try fromSlice(f32, .{3537 try std.testing.expectEqual(@as(f32, @floatFromInt(0x1ffffffffffffffff)), try fromSliceNoAlloc(f32, .{
3441 .gpa = gpa,3538 .gpa = gpa,
3539 .arena = arena,
3442 .source = "0x1ffffffffffffffff",3540 .source = "0x1ffffffffffffffff",
3443 .errors = null,3541 .errors = &errors,
3444 }));3542 }));
34453543
3446 // Exponents, underscores3544 // Exponents, underscores
3447 try std.testing.expectEqual(3545 try std.testing.expectEqual(
3448 @as(f32, 123.0E+77),3546 @as(f32, 123.0E+77),
3449 try fromSlice(f32, .{3547 try fromSliceNoAlloc(f32, .{
3450 .gpa = gpa,3548 .gpa = gpa,
3549 .arena = arena,
3451 .source = "12_3.0E+77",3550 .source = "12_3.0E+77",
3452 .errors = null,3551 .errors = &errors,
3453 }),3552 }),
3454 );3553 );
34553554
3456 // Hexadecimal3555 // Hexadecimal
3457 try std.testing.expectEqual(3556 try std.testing.expectEqual(
3458 @as(f32, 0x103.70p-5),3557 @as(f32, 0x103.70p-5),
3459 try fromSlice(f32, .{3558 try fromSliceNoAlloc(f32, .{
3460 .gpa = gpa,3559 .gpa = gpa,
3560 .arena = arena,
3461 .source = "0x103.70p-5",3561 .source = "0x103.70p-5",
3462 .errors = null,3562 .errors = &errors,
3463 }),3563 }),
3464 );3564 );
3465 try std.testing.expectEqual(3565 try std.testing.expectEqual(
3466 @as(f32, -0x103.70),3566 @as(f32, -0x103.70),
3467 try fromSlice(f32, .{3567 try fromSliceNoAlloc(f32, .{
3468 .gpa = gpa,3568 .gpa = gpa,
3569 .arena = arena,
3469 .source = "-0x103.70",3570 .source = "-0x103.70",
3470 .errors = null,3571 .errors = &errors,
3471 }),3572 }),
3472 );3573 );
3473 try std.testing.expectEqual(3574 try std.testing.expectEqual(
3474 @as(f32, 0x1234_5678.9ABC_CDEFp-10),3575 @as(f32, 0x1234_5678.9ABC_CDEFp-10),
3475 try fromSlice(f32, .{3576 try fromSliceNoAlloc(f32, .{
3476 .gpa = gpa,3577 .gpa = gpa,
3578 .arena = arena,
3477 .source = "0x1234_5678.9ABC_CDEFp-10",3579 .source = "0x1234_5678.9ABC_CDEFp-10",
3478 .errors = null,3580 .errors = &errors,
3479 }),3581 }),
3480 );3582 );
34813583
3482 // inf, nan3584 // inf, nan
3483 try std.testing.expect(std.math.isPositiveInf(try fromSlice(f32, .{3585 try std.testing.expect(std.math.isPositiveInf(try fromSliceNoAlloc(f32, .{
3484 .gpa = gpa,3586 .gpa = gpa,
3587 .arena = arena,
3485 .source = "inf",3588 .source = "inf",
3486 .errors = null,3589 .errors = &errors,
3487 })));3590 })));
3488 try std.testing.expect(std.math.isNegativeInf(try fromSlice(f32, .{3591 try std.testing.expect(std.math.isNegativeInf(try fromSliceNoAlloc(f32, .{
3489 .gpa = gpa,3592 .gpa = gpa,
3593 .arena = arena,
3490 .source = "-inf",3594 .source = "-inf",
3491 .errors = null,3595 .errors = &errors,
3492 })));3596 })));
3493 try std.testing.expect(std.math.isNan(try fromSlice(f32, .{3597 try std.testing.expect(std.math.isNan(try fromSliceNoAlloc(f32, .{
3494 .gpa = gpa,3598 .gpa = gpa,
3599 .arena = arena,
3495 .source = "nan",3600 .source = "nan",
3496 .errors = null,3601 .errors = &errors,
3497 })));3602 })));
34983603
3499 // Negative nan not allowed3604 // Negative nan not allowed
3500 {3605 {
3501 var errors: Errors = .init(arena);3606 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(f32, .{
3502 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3503 .gpa = gpa,3607 .gpa = gpa,
3608 .arena = arena,
3504 .source = "-nan",3609 .source = "-nan",
3505 .errors = &errors,3610 .errors = &errors,
3506 }));3611 }));
3507 try std.testing.expectFmt("input.zon:1:1: error: expected number or 'inf' after '-'\n", "{f}", .{errors.fmt("input.zon")});3612 try std.testing.expectFmt(
3613 \\input.zon: error.ParseZon
3614 \\input.zon:1:1: error: expected number or 'inf' after '-'
3615 \\
3616 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3508 }3617 }
35093618
3510 // nan as int not allowed3619 // nan as int not allowed
3511 {3620 {
3512 var errors: Errors = .init(arena);3621 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3513 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3514 .gpa = gpa,3622 .gpa = gpa,
3623 .arena = arena,
3515 .source = "nan",3624 .source = "nan",
3516 .errors = &errors,3625 .errors = &errors,
3517 }));3626 }));
3518 try std.testing.expectFmt(3627 try std.testing.expectFmt(
3628 \\input.zon: error.ParseZon
3519 \\input.zon:1:1: error: expected type 'i8'3629 \\input.zon:1:1: error: expected type 'i8'
3520 \\3630 \\
3521 , "{f}", .{errors.fmt("input.zon")});3631 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3522 }3632 }
35233633
3524 // nan as int not allowed3634 // nan as int not allowed
3525 {3635 {
3526 var errors: Errors = .init(arena);3636 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3527 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3528 .gpa = gpa,3637 .gpa = gpa,
3638 .arena = arena,
3529 .source = "nan",3639 .source = "nan",
3530 .errors = &errors,3640 .errors = &errors,
3531 }));3641 }));
3532 try std.testing.expectFmt(3642 try std.testing.expectFmt(
3643 \\input.zon: error.ParseZon
3533 \\input.zon:1:1: error: expected type 'i8'3644 \\input.zon:1:1: error: expected type 'i8'
3534 \\3645 \\
3535 , "{f}", .{errors.fmt("input.zon")});3646 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3536 }3647 }
35373648
3538 // inf as int not allowed3649 // inf as int not allowed
3539 {3650 {
3540 var errors: Errors = .init(arena);3651 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3541 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3542 .gpa = gpa,3652 .gpa = gpa,
3653 .arena = arena,
3543 .source = "inf",3654 .source = "inf",
3544 .errors = &errors,3655 .errors = &errors,
3545 }));3656 }));
3546 try std.testing.expectFmt(3657 try std.testing.expectFmt(
3658 \\input.zon: error.ParseZon
3547 \\input.zon:1:1: error: expected type 'i8'3659 \\input.zon:1:1: error: expected type 'i8'
3548 \\3660 \\
3549 , "{f}", .{errors.fmt("input.zon")});3661 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3550 }3662 }
35513663
3552 // -inf as int not allowed3664 // -inf as int not allowed
3553 {3665 {
3554 var errors: Errors = .init(arena);3666 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(i8, .{
3555 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
3556 .gpa = gpa,3667 .gpa = gpa,
3668 .arena = arena,
3557 .source = "-inf",3669 .source = "-inf",
3558 .errors = &errors,3670 .errors = &errors,
3559 }));3671 }));
3560 try std.testing.expectFmt(3672 try std.testing.expectFmt(
3673 \\input.zon: error.ParseZon
3561 \\input.zon:1:1: error: expected type 'i8'3674 \\input.zon:1:1: error: expected type 'i8'
3562 \\3675 \\
3563 , "{f}", .{errors.fmt("input.zon")});3676 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3564 }3677 }
35653678
3566 // Bad identifier as float3679 // Bad identifier as float
3567 {3680 {
3568 var errors: Errors = .init(arena);3681 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(f32, .{
3569 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3570 .gpa = gpa,3682 .gpa = gpa,
3683 .arena = arena,
3571 .source = "foo",3684 .source = "foo",
3572 .errors = &errors,3685 .errors = &errors,
3573 }));3686 }));
3574 try std.testing.expectFmt(3687 try std.testing.expectFmt(
3688 \\input.zon: error.ParseZon
3575 \\input.zon:1:1: error: invalid expression3689 \\input.zon:1:1: error: invalid expression
3576 \\input.zon:1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'3690 \\input.zon:1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
3577 \\input.zon:1:1: note: precede identifier with '.' for an enum literal3691 \\input.zon:1:1: note: precede identifier with '.' for an enum literal
3578 \\3692 \\
3579 , "{f}", .{errors.fmt("input.zon")});3693 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3580 }3694 }
35813695
3582 {3696 {
3583 var errors: Errors = .init(arena);3697 try std.testing.expectError(error.ParseZon, fromSliceNoAlloc(f32, .{
3584 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
3585 .gpa = gpa,3698 .gpa = gpa,
3699 .arena = arena,
3586 .source = "-foo",3700 .source = "-foo",
3587 .errors = &errors,3701 .errors = &errors,
3588 }));3702 }));
3589 try std.testing.expectFmt(3703 try std.testing.expectFmt(
3704 \\input.zon: error.ParseZon
3590 \\input.zon:1:1: error: expected number or 'inf' after '-'3705 \\input.zon:1:1: error: expected number or 'inf' after '-'
3591 \\3706 \\
3592 , "{f}", .{errors.fmt("input.zon")});3707 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3593 }3708 }
35943709
3595 // Non float as float3710 // Non float as float
3596 {3711 {
3597 var errors: Errors = .init(arena);
3598 try std.testing.expectError(3712 try std.testing.expectError(
3599 error.ParseZon,3713 error.ParseZon,
3600 fromSlice(f32, .{3714 fromSliceNoAlloc(f32, .{
3601 .gpa = gpa,3715 .gpa = gpa,
3716 .arena = arena,
3602 .source = "\"foo\"",3717 .source = "\"foo\"",
3603 .errors = &errors,3718 .errors = &errors,
3604 }),3719 }),
3605 );3720 );
3606 try std.testing.expectFmt(3721 try std.testing.expectFmt(
3722 \\input.zon: error.ParseZon
3607 \\input.zon:1:1: error: expected type 'f32'3723 \\input.zon:1:1: error: expected type 'f32'
3608 \\3724 \\
3609 , "{f}", .{errors.fmt("input.zon")});3725 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3610 }3726 }
3611}3727}
36123728
...@@ -3615,6 +3731,7 @@ test "std.zon free on error" {...@@ -3615,6 +3731,7 @@ test "std.zon free on error" {
3615 var arena_allocator: ArenaAllocator = .init(gpa);3731 var arena_allocator: ArenaAllocator = .init(gpa);
3616 defer arena_allocator.deinit();3732 defer arena_allocator.deinit();
3617 const arena = arena_allocator.allocator();3733 const arena = arena_allocator.allocator();
3734 var errors: Errors = .empty;
36183735
3619 // Test freeing partially allocated structs3736 // Test freeing partially allocated structs
3620 {3737 {
...@@ -3623,7 +3740,7 @@ test "std.zon free on error" {...@@ -3623,7 +3740,7 @@ test "std.zon free on error" {
3623 y: []const u8,3740 y: []const u8,
3624 z: bool,3741 z: bool,
3625 };3742 };
3626 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{3743 try std.testing.expectError(error.ParseZon, fromSlice(Struct, .{
3627 .gpa = gpa,3744 .gpa = gpa,
3628 .arena = arena,3745 .arena = arena,
3629 .source =3746 .source =
...@@ -3633,7 +3750,7 @@ test "std.zon free on error" {...@@ -3633,7 +3750,7 @@ test "std.zon free on error" {
3633 \\ .z = "fail",3750 \\ .z = "fail",
3634 \\}3751 \\}
3635 ,3752 ,
3636 .errors = null,3753 .errors = &errors,
3637 }));3754 }));
3638 }3755 }
36393756
...@@ -3644,7 +3761,7 @@ test "std.zon free on error" {...@@ -3644,7 +3761,7 @@ test "std.zon free on error" {
3644 []const u8,3761 []const u8,
3645 bool,3762 bool,
3646 };3763 };
3647 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{3764 try std.testing.expectError(error.ParseZon, fromSlice(Struct, .{
3648 .gpa = gpa,3765 .gpa = gpa,
3649 .arena = arena,3766 .arena = arena,
3650 .source =3767 .source =
...@@ -3654,7 +3771,7 @@ test "std.zon free on error" {...@@ -3654,7 +3771,7 @@ test "std.zon free on error" {
3654 \\ "fail",3771 \\ "fail",
3655 \\}3772 \\}
3656 ,3773 ,
3657 .errors = null,3774 .errors = &errors,
3658 }));3775 }));
3659 }3776 }
36603777
...@@ -3663,7 +3780,7 @@ test "std.zon free on error" {...@@ -3663,7 +3780,7 @@ test "std.zon free on error" {
3663 x: []const u8,3780 x: []const u8,
3664 y: bool,3781 y: bool,
3665 };3782 };
3666 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{3783 try std.testing.expectError(error.ParseZon, fromSlice(Struct, .{
3667 .gpa = gpa,3784 .gpa = gpa,
3668 .arena = arena,3785 .arena = arena,
3669 .source =3786 .source =
...@@ -3671,11 +3788,11 @@ test "std.zon free on error" {...@@ -3671,11 +3788,11 @@ test "std.zon free on error" {
3671 \\ .x = "hello",3788 \\ .x = "hello",
3672 \\}3789 \\}
3673 ,3790 ,
3674 .errors = null,3791 .errors = &errors,
3675 }));3792 }));
36763793
3677 // Test freeing partially allocated arrays3794 // Test freeing partially allocated arrays
3678 try std.testing.expectError(error.ParseZon, fromSliceAlloc([3][]const u8, .{3795 try std.testing.expectError(error.ParseZon, fromSlice([3][]const u8, .{
3679 .gpa = gpa,3796 .gpa = gpa,
3680 .arena = arena,3797 .arena = arena,
3681 .source =3798 .source =
...@@ -3685,11 +3802,11 @@ test "std.zon free on error" {...@@ -3685,11 +3802,11 @@ test "std.zon free on error" {
3685 \\ false,3802 \\ false,
3686 \\}3803 \\}
3687 ,3804 ,
3688 .errors = null,3805 .errors = &errors,
3689 }));3806 }));
36903807
3691 // Test freeing partially allocated slices3808 // Test freeing partially allocated slices
3692 try std.testing.expectError(error.ParseZon, fromSliceAlloc([][]const u8, .{3809 try std.testing.expectError(error.ParseZon, fromSlice([][]const u8, .{
3693 .gpa = gpa,3810 .gpa = gpa,
3694 .arena = arena,3811 .arena = arena,
3695 .source =3812 .source =
...@@ -3699,28 +3816,29 @@ test "std.zon free on error" {...@@ -3699,28 +3816,29 @@ test "std.zon free on error" {
3699 \\ false,3816 \\ false,
3700 \\}3817 \\}
3701 ,3818 ,
3702 .errors = null,3819 .errors = &errors,
3703 }));3820 }));
37043821
3705 // We can parse types that can't be freed, as long as they contain no allocations, e.g. untagged3822 // We can parse types that can't be freed, as long as they contain no allocations, e.g. untagged
3706 // unions.3823 // unions.
3707 try std.testing.expectEqual(3824 try std.testing.expectEqual(
3708 @as(f32, 1.5),3825 @as(f32, 1.5),
3709 (try fromSlice(union { x: f32 }, .{3826 (try fromSliceNoAlloc(union { x: f32 }, .{
3710 .gpa = gpa,3827 .gpa = gpa,
3828 .arena = arena,
3711 .source = ".{ .x = 1.5 }",3829 .source = ".{ .x = 1.5 }",
3712 .errors = null,3830 .errors = &errors,
3713 })).x,3831 })).x,
3714 );3832 );
37153833
3716 // We can also parse types that can't be freed if it's impossible for an error to occur after3834 // We can also parse types that can't be freed if it's impossible for an error to occur after
3717 // the allocation, as is the case here.3835 // the allocation, as is the case here.
3718 {3836 {
3719 const result = try fromSliceAlloc(union { x: []const u8 }, .{3837 const result = try fromSlice(union { x: []const u8 }, .{
3720 .gpa = gpa,3838 .gpa = gpa,
3721 .arena = arena,3839 .arena = arena,
3722 .source = ".{ .x = \"foo\" }",3840 .source = ".{ .x = \"foo\" }",
3723 .errors = null,3841 .errors = &errors,
3724 });3842 });
3725 try std.testing.expectEqualStrings("foo", result.x);3843 try std.testing.expectEqualStrings("foo", result.x);
3726 }3844 }
...@@ -3734,74 +3852,81 @@ test "std.zon vector" {...@@ -3734,74 +3852,81 @@ test "std.zon vector" {
3734 var arena_allocator: ArenaAllocator = .init(gpa);3852 var arena_allocator: ArenaAllocator = .init(gpa);
3735 defer arena_allocator.deinit();3853 defer arena_allocator.deinit();
3736 const arena = arena_allocator.allocator();3854 const arena = arena_allocator.allocator();
3855 var errors: Errors = .empty;
37373856
3738 // Passing cases3857 // Passing cases
3739 try std.testing.expectEqual(3858 try std.testing.expectEqual(
3740 @Vector(0, bool){},3859 @Vector(0, bool){},
3741 try fromSlice(@Vector(0, bool), .{3860 try fromSliceNoAlloc(@Vector(0, bool), .{
3742 .gpa = gpa,3861 .gpa = gpa,
3862 .arena = arena,
3743 .source = ".{}",3863 .source = ".{}",
3744 .errors = null,3864 .errors = &errors,
3745 }),3865 }),
3746 );3866 );
3747 try std.testing.expectEqual(3867 try std.testing.expectEqual(
3748 @Vector(3, bool){ true, false, true },3868 @Vector(3, bool){ true, false, true },
3749 try fromSlice(@Vector(3, bool), .{3869 try fromSliceNoAlloc(@Vector(3, bool), .{
3750 .gpa = gpa,3870 .gpa = gpa,
3871 .arena = arena,
3751 .source = ".{true, false, true}",3872 .source = ".{true, false, true}",
3752 .errors = null,3873 .errors = &errors,
3753 }),3874 }),
3754 );3875 );
37553876
3756 try std.testing.expectEqual(3877 try std.testing.expectEqual(
3757 @Vector(0, f32){},3878 @Vector(0, f32){},
3758 try fromSlice(@Vector(0, f32), .{3879 try fromSliceNoAlloc(@Vector(0, f32), .{
3759 .gpa = gpa,3880 .gpa = gpa,
3881 .arena = arena,
3760 .source = ".{}",3882 .source = ".{}",
3761 .errors = null,3883 .errors = &errors,
3762 }),3884 }),
3763 );3885 );
3764 try std.testing.expectEqual(3886 try std.testing.expectEqual(
3765 @Vector(3, f32){ 1.5, 2.5, 3.5 },3887 @Vector(3, f32){ 1.5, 2.5, 3.5 },
3766 try fromSlice(@Vector(3, f32), .{3888 try fromSliceNoAlloc(@Vector(3, f32), .{
3767 .gpa = gpa,3889 .gpa = gpa,
3890 .arena = arena,
3768 .source = ".{1.5, 2.5, 3.5}",3891 .source = ".{1.5, 2.5, 3.5}",
3769 .errors = null,3892 .errors = &errors,
3770 }),3893 }),
3771 );3894 );
37723895
3773 try std.testing.expectEqual(3896 try std.testing.expectEqual(
3774 @Vector(0, u8){},3897 @Vector(0, u8){},
3775 try fromSlice(@Vector(0, u8), .{3898 try fromSliceNoAlloc(@Vector(0, u8), .{
3776 .gpa = gpa,3899 .gpa = gpa,
3900 .arena = arena,
3777 .source = ".{}",3901 .source = ".{}",
3778 .errors = null,3902 .errors = &errors,
3779 }),3903 }),
3780 );3904 );
3781 try std.testing.expectEqual(3905 try std.testing.expectEqual(
3782 @Vector(3, u8){ 2, 4, 6 },3906 @Vector(3, u8){ 2, 4, 6 },
3783 try fromSlice(@Vector(3, u8), .{3907 try fromSliceNoAlloc(@Vector(3, u8), .{
3784 .gpa = gpa,3908 .gpa = gpa,
3909 .arena = arena,
3785 .source = ".{2, 4, 6}",3910 .source = ".{2, 4, 6}",
3786 .errors = null,3911 .errors = &errors,
3787 }),3912 }),
3788 );3913 );
37893914
3790 {3915 {
3791 try std.testing.expectEqual(3916 try std.testing.expectEqual(
3792 @Vector(0, *const u8){},3917 @Vector(0, *const u8){},
3793 try fromSliceAlloc(@Vector(0, *const u8), .{3918 try fromSlice(@Vector(0, *const u8), .{
3794 .gpa = gpa,3919 .gpa = gpa,
3795 .arena = arena,3920 .arena = arena,
3796 .source = ".{}",3921 .source = ".{}",
3797 .errors = null,3922 .errors = &errors,
3798 }),3923 }),
3799 );3924 );
3800 const pointers = try fromSliceAlloc(@Vector(3, *const u8), .{3925 const pointers = try fromSlice(@Vector(3, *const u8), .{
3801 .gpa = gpa,3926 .gpa = gpa,
3802 .arena = arena,3927 .arena = arena,
3803 .source = ".{2, 4, 6}",3928 .source = ".{2, 4, 6}",
3804 .errors = null,3929 .errors = &errors,
3805 });3930 });
3806 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);3931 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);
3807 }3932 }
...@@ -3809,96 +3934,99 @@ test "std.zon vector" {...@@ -3809,96 +3934,99 @@ test "std.zon vector" {
3809 {3934 {
3810 try std.testing.expectEqual(3935 try std.testing.expectEqual(
3811 @Vector(0, ?*const u8){},3936 @Vector(0, ?*const u8){},
3812 try fromSliceAlloc(@Vector(0, ?*const u8), .{3937 try fromSlice(@Vector(0, ?*const u8), .{
3813 .gpa = gpa,3938 .gpa = gpa,
3814 .arena = arena,3939 .arena = arena,
3815 .source = ".{}",3940 .source = ".{}",
3816 .errors = null,3941 .errors = &errors,
3817 }),3942 }),
3818 );3943 );
3819 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), .{3944 const pointers = try fromSlice(@Vector(3, ?*const u8), .{
3820 .gpa = gpa,3945 .gpa = gpa,
3821 .arena = arena,3946 .arena = arena,
3822 .source = ".{2, null, 6}",3947 .source = ".{2, null, 6}",
3823 .errors = null,3948 .errors = &errors,
3824 });3949 });
3825 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);3950 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);
3826 }3951 }
38273952
3828 // Too few fields3953 // Too few fields
3829 {3954 {
3830 var errors: Errors = .init(arena);
3831 try std.testing.expectError(3955 try std.testing.expectError(
3832 error.ParseZon,3956 error.ParseZon,
3833 fromSlice(@Vector(2, f32), .{3957 fromSliceNoAlloc(@Vector(2, f32), .{
3834 .gpa = gpa,3958 .gpa = gpa,
3959 .arena = arena,
3835 .source = ".{0.5}",3960 .source = ".{0.5}",
3836 .errors = &errors,3961 .errors = &errors,
3837 }),3962 }),
3838 );3963 );
3839 try std.testing.expectFmt(3964 try std.testing.expectFmt(
3965 \\input.zon: error.ParseZon
3840 \\input.zon:1:2: error: expected 2 array elements; found 13966 \\input.zon:1:2: error: expected 2 array elements; found 1
3841 \\3967 \\
3842 , "{f}", .{errors.fmt("input.zon")});3968 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3843 }3969 }
38443970
3845 // Too many fields3971 // Too many fields
3846 {3972 {
3847 var errors: Errors = .init(arena);
3848 try std.testing.expectError(3973 try std.testing.expectError(
3849 error.ParseZon,3974 error.ParseZon,
3850 fromSlice(@Vector(2, f32), .{3975 fromSliceNoAlloc(@Vector(2, f32), .{
3851 .gpa = gpa,3976 .gpa = gpa,
3977 .arena = arena,
3852 .source = ".{0.5, 1.5, 2.5}",3978 .source = ".{0.5, 1.5, 2.5}",
3853 .errors = &errors,3979 .errors = &errors,
3854 }),3980 }),
3855 );3981 );
3856 try std.testing.expectFmt(3982 try std.testing.expectFmt(
3983 \\input.zon: error.ParseZon
3857 \\input.zon:1:13: error: index 2 outside of array of length 23984 \\input.zon:1:13: error: index 2 outside of array of length 2
3858 \\3985 \\
3859 , "{f}", .{errors.fmt("input.zon")});3986 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3860 }3987 }
38613988
3862 // Wrong type fields3989 // Wrong type fields
3863 {3990 {
3864 var errors: Errors = .init(arena);
3865 try std.testing.expectError(3991 try std.testing.expectError(
3866 error.ParseZon,3992 error.ParseZon,
3867 fromSlice(@Vector(3, f32), .{3993 fromSliceNoAlloc(@Vector(3, f32), .{
3868 .gpa = gpa,3994 .gpa = gpa,
3995 .arena = arena,
3869 .source = ".{0.5, true, 2.5}",3996 .source = ".{0.5, true, 2.5}",
3870 .errors = &errors,3997 .errors = &errors,
3871 }),3998 }),
3872 );3999 );
3873 try std.testing.expectFmt(4000 try std.testing.expectFmt(
4001 \\input.zon: error.ParseZon
3874 \\input.zon:1:8: error: expected type 'f32'4002 \\input.zon:1:8: error: expected type 'f32'
3875 \\4003 \\
3876 , "{f}", .{errors.fmt("input.zon")});4004 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3877 }4005 }
38784006
3879 // Wrong type4007 // Wrong type
3880 {4008 {
3881 var errors: Errors = .init(arena);
3882 try std.testing.expectError(4009 try std.testing.expectError(
3883 error.ParseZon,4010 error.ParseZon,
3884 fromSlice(@Vector(3, u8), .{4011 fromSliceNoAlloc(@Vector(3, u8), .{
3885 .gpa = gpa,4012 .gpa = gpa,
4013 .arena = arena,
3886 .source = "true",4014 .source = "true",
3887 .errors = &errors,4015 .errors = &errors,
3888 }),4016 }),
3889 );4017 );
3890 try std.testing.expectFmt(4018 try std.testing.expectFmt(
4019 \\input.zon: error.ParseZon
3891 \\input.zon:1:1: error: expected type '@Vector(3, u8)'4020 \\input.zon:1:1: error: expected type '@Vector(3, u8)'
3892 \\4021 \\
3893 , "{f}", .{errors.fmt("input.zon")});4022 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3894 }4023 }
38954024
3896 // Elements should get freed on error4025 // Elements should get freed on error
3897 {4026 {
3898 var errors: Errors = .init(arena);
3899 try std.testing.expectError(4027 try std.testing.expectError(
3900 error.ParseZon,4028 error.ParseZon,
3901 fromSliceAlloc(@Vector(3, *u8), .{4029 fromSlice(@Vector(3, *u8), .{
3902 .gpa = gpa,4030 .gpa = gpa,
3903 .arena = arena,4031 .arena = arena,
3904 .source = ".{1, true, 3}",4032 .source = ".{1, true, 3}",
...@@ -3906,9 +4034,10 @@ test "std.zon vector" {...@@ -3906,9 +4034,10 @@ test "std.zon vector" {
3906 }),4034 }),
3907 );4035 );
3908 try std.testing.expectFmt(4036 try std.testing.expectFmt(
4037 \\input.zon: error.ParseZon
3909 \\input.zon:1:6: error: expected type 'u8'4038 \\input.zon:1:6: error: expected type 'u8'
3910 \\4039 \\
3911 , "{f}", .{errors.fmt("input.zon")});4040 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
3912 }4041 }
3913}4042}
39144043
...@@ -3917,136 +4046,137 @@ test "std.zon add pointers" {...@@ -3917,136 +4046,137 @@ test "std.zon add pointers" {
3917 var arena_allocator: ArenaAllocator = .init(gpa);4046 var arena_allocator: ArenaAllocator = .init(gpa);
3918 defer arena_allocator.deinit();4047 defer arena_allocator.deinit();
3919 const arena = arena_allocator.allocator();4048 const arena = arena_allocator.allocator();
4049 var errors: Errors = .empty;
39204050
3921 // Primitive with varying levels of pointers4051 // Primitive with varying levels of pointers
3922 {4052 {
3923 const result = try fromSliceAlloc(*u32, .{4053 const result = try fromSlice(*u32, .{
3924 .gpa = gpa,4054 .gpa = gpa,
3925 .arena = arena,4055 .arena = arena,
3926 .source = "10",4056 .source = "10",
3927 .errors = null,4057 .errors = &errors,
3928 });4058 });
3929 try std.testing.expectEqual(@as(u32, 10), result.*);4059 try std.testing.expectEqual(@as(u32, 10), result.*);
3930 }4060 }
39314061
3932 {4062 {
3933 const result = try fromSliceAlloc(**u32, .{4063 const result = try fromSlice(**u32, .{
3934 .gpa = gpa,4064 .gpa = gpa,
3935 .arena = arena,4065 .arena = arena,
3936 .source = "10",4066 .source = "10",
3937 .errors = null,4067 .errors = &errors,
3938 });4068 });
3939 try std.testing.expectEqual(@as(u32, 10), result.*.*);4069 try std.testing.expectEqual(@as(u32, 10), result.*.*);
3940 }4070 }
39414071
3942 {4072 {
3943 const result = try fromSliceAlloc(***u32, .{4073 const result = try fromSlice(***u32, .{
3944 .gpa = gpa,4074 .gpa = gpa,
3945 .arena = arena,4075 .arena = arena,
3946 .source = "10",4076 .source = "10",
3947 .errors = null,4077 .errors = &errors,
3948 });4078 });
3949 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);4079 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);
3950 }4080 }
39514081
3952 // Primitive optional with varying levels of pointers4082 // Primitive optional with varying levels of pointers
3953 {4083 {
3954 const some = try fromSliceAlloc(?*u32, .{4084 const some = try fromSlice(?*u32, .{
3955 .gpa = gpa,4085 .gpa = gpa,
3956 .arena = arena,4086 .arena = arena,
3957 .source = "10",4087 .source = "10",
3958 .errors = null,4088 .errors = &errors,
3959 });4089 });
3960 try std.testing.expectEqual(@as(u32, 10), some.?.*);4090 try std.testing.expectEqual(@as(u32, 10), some.?.*);
39614091
3962 const none = try fromSliceAlloc(?*u32, .{4092 const none = try fromSlice(?*u32, .{
3963 .gpa = gpa,4093 .gpa = gpa,
3964 .arena = arena,4094 .arena = arena,
3965 .source = "null",4095 .source = "null",
3966 .errors = null,4096 .errors = &errors,
3967 });4097 });
3968 try std.testing.expectEqual(null, none);4098 try std.testing.expectEqual(null, none);
3969 }4099 }
39704100
3971 {4101 {
3972 const some = try fromSliceAlloc(*?u32, .{4102 const some = try fromSlice(*?u32, .{
3973 .gpa = gpa,4103 .gpa = gpa,
3974 .arena = arena,4104 .arena = arena,
3975 .source = "10",4105 .source = "10",
3976 .errors = null,4106 .errors = &errors,
3977 });4107 });
3978 try std.testing.expectEqual(@as(u32, 10), some.*.?);4108 try std.testing.expectEqual(@as(u32, 10), some.*.?);
39794109
3980 const none = try fromSliceAlloc(*?u32, .{4110 const none = try fromSlice(*?u32, .{
3981 .gpa = gpa,4111 .gpa = gpa,
3982 .arena = arena,4112 .arena = arena,
3983 .source = "null",4113 .source = "null",
3984 .errors = null,4114 .errors = &errors,
3985 });4115 });
3986 try std.testing.expectEqual(null, none.*);4116 try std.testing.expectEqual(null, none.*);
3987 }4117 }
39884118
3989 {4119 {
3990 const some = try fromSliceAlloc(?**u32, .{4120 const some = try fromSlice(?**u32, .{
3991 .gpa = gpa,4121 .gpa = gpa,
3992 .arena = arena,4122 .arena = arena,
3993 .source = "10",4123 .source = "10",
3994 .errors = null,4124 .errors = &errors,
3995 });4125 });
3996 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);4126 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);
39974127
3998 const none = try fromSliceAlloc(?**u32, .{4128 const none = try fromSlice(?**u32, .{
3999 .gpa = gpa,4129 .gpa = gpa,
4000 .arena = arena,4130 .arena = arena,
4001 .source = "null",4131 .source = "null",
4002 .errors = null,4132 .errors = &errors,
4003 });4133 });
4004 try std.testing.expectEqual(null, none);4134 try std.testing.expectEqual(null, none);
4005 }4135 }
40064136
4007 {4137 {
4008 const some = try fromSliceAlloc(*?*u32, .{4138 const some = try fromSlice(*?*u32, .{
4009 .gpa = gpa,4139 .gpa = gpa,
4010 .arena = arena,4140 .arena = arena,
4011 .source = "10",4141 .source = "10",
4012 .errors = null,4142 .errors = &errors,
4013 });4143 });
4014 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);4144 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);
40154145
4016 const none = try fromSliceAlloc(*?*u32, .{4146 const none = try fromSlice(*?*u32, .{
4017 .gpa = gpa,4147 .gpa = gpa,
4018 .arena = arena,4148 .arena = arena,
4019 .source = "null",4149 .source = "null",
4020 .errors = null,4150 .errors = &errors,
4021 });4151 });
4022 try std.testing.expectEqual(null, none.*);4152 try std.testing.expectEqual(null, none.*);
4023 }4153 }
40244154
4025 {4155 {
4026 const some = try fromSliceAlloc(**?u32, .{4156 const some = try fromSlice(**?u32, .{
4027 .gpa = gpa,4157 .gpa = gpa,
4028 .arena = arena,4158 .arena = arena,
4029 .source = "10",4159 .source = "10",
4030 .errors = null,4160 .errors = &errors,
4031 });4161 });
4032 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);4162 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);
40334163
4034 const none = try fromSliceAlloc(**?u32, .{4164 const none = try fromSlice(**?u32, .{
4035 .gpa = gpa,4165 .gpa = gpa,
4036 .arena = arena,4166 .arena = arena,
4037 .source = "null",4167 .source = "null",
4038 .errors = null,4168 .errors = &errors,
4039 });4169 });
4040 try std.testing.expectEqual(null, none.*.*);4170 try std.testing.expectEqual(null, none.*.*);
4041 }4171 }
40424172
4043 // Pointer to an array4173 // Pointer to an array
4044 {4174 {
4045 const result = try fromSliceAlloc(*[3]u8, .{4175 const result = try fromSlice(*[3]u8, .{
4046 .gpa = gpa,4176 .gpa = gpa,
4047 .arena = arena,4177 .arena = arena,
4048 .source = ".{ 1, 2, 3 }",4178 .source = ".{ 1, 2, 3 }",
4049 .errors = null,4179 .errors = &errors,
4050 });4180 });
4051 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);4181 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);
4052 }4182 }
...@@ -4069,7 +4199,7 @@ test "std.zon add pointers" {...@@ -4069,7 +4199,7 @@ test "std.zon add pointers" {
4069 .f2 = &null,4199 .f2 = &null,
4070 };4200 };
40714201
4072 const found = try fromSliceAlloc(?*Outer, .{4202 const found = try fromSlice(?*Outer, .{
4073 .gpa = gpa,4203 .gpa = gpa,
4074 .arena = arena,4204 .arena = arena,
4075 .source =4205 .source =
...@@ -4081,7 +4211,7 @@ test "std.zon add pointers" {...@@ -4081,7 +4211,7 @@ test "std.zon add pointers" {
4081 \\ .f2 = null,4211 \\ .f2 = null,
4082 \\}4212 \\}
4083 ,4213 ,
4084 .errors = null,4214 .errors = &errors,
4085 });4215 });
40864216
4087 try std.testing.expectEqualDeep(expected, found.?.*);4217 try std.testing.expectEqualDeep(expected, found.?.*);
...@@ -4089,10 +4219,9 @@ test "std.zon add pointers" {...@@ -4089,10 +4219,9 @@ test "std.zon add pointers" {
40894219
4090 // Test that optional types are flattened correctly in errors4220 // Test that optional types are flattened correctly in errors
4091 {4221 {
4092 var errors: Errors = .init(arena);
4093 try std.testing.expectError(4222 try std.testing.expectError(
4094 error.ParseZon,4223 error.ParseZon,
4095 fromSliceAlloc(*const ?*const u8, .{4224 fromSlice(*const ?*const u8, .{
4096 .gpa = gpa,4225 .gpa = gpa,
4097 .arena = arena,4226 .arena = arena,
4098 .source = "true",4227 .source = "true",
...@@ -4100,16 +4229,16 @@ test "std.zon add pointers" {...@@ -4100,16 +4229,16 @@ test "std.zon add pointers" {
4100 }),4229 }),
4101 );4230 );
4102 try std.testing.expectFmt(4231 try std.testing.expectFmt(
4232 \\input.zon: error.ParseZon
4103 \\input.zon:1:1: error: expected type '?u8'4233 \\input.zon:1:1: error: expected type '?u8'
4104 \\4234 \\
4105 , "{f}", .{errors.fmt("input.zon")});4235 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4106 }4236 }
41074237
4108 {4238 {
4109 var errors: Errors = .init(arena);
4110 try std.testing.expectError(4239 try std.testing.expectError(
4111 error.ParseZon,4240 error.ParseZon,
4112 fromSliceAlloc(*const ?*const f32, .{4241 fromSlice(*const ?*const f32, .{
4113 .gpa = gpa,4242 .gpa = gpa,
4114 .arena = arena,4243 .arena = arena,
4115 .source = "true",4244 .source = "true",
...@@ -4117,16 +4246,16 @@ test "std.zon add pointers" {...@@ -4117,16 +4246,16 @@ test "std.zon add pointers" {
4117 }),4246 }),
4118 );4247 );
4119 try std.testing.expectFmt(4248 try std.testing.expectFmt(
4249 \\input.zon: error.ParseZon
4120 \\input.zon:1:1: error: expected type '?f32'4250 \\input.zon:1:1: error: expected type '?f32'
4121 \\4251 \\
4122 , "{f}", .{errors.fmt("input.zon")});4252 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4123 }4253 }
41244254
4125 {4255 {
4126 var errors: Errors = .init(arena);
4127 try std.testing.expectError(4256 try std.testing.expectError(
4128 error.ParseZon,4257 error.ParseZon,
4129 fromSliceAlloc(*const ?*const @Vector(3, u8), .{4258 fromSlice(*const ?*const @Vector(3, u8), .{
4130 .gpa = gpa,4259 .gpa = gpa,
4131 .arena = arena,4260 .arena = arena,
4132 .source = "true",4261 .source = "true",
...@@ -4134,16 +4263,16 @@ test "std.zon add pointers" {...@@ -4134,16 +4263,16 @@ test "std.zon add pointers" {
4134 }),4263 }),
4135 );4264 );
4136 try std.testing.expectFmt(4265 try std.testing.expectFmt(
4266 \\input.zon: error.ParseZon
4137 \\input.zon:1:1: error: expected type '?@Vector(3, u8)'4267 \\input.zon:1:1: error: expected type '?@Vector(3, u8)'
4138 \\4268 \\
4139 , "{f}", .{errors.fmt("input.zon")});4269 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4140 }4270 }
41414271
4142 {4272 {
4143 var errors: Errors = .init(arena);
4144 try std.testing.expectError(4273 try std.testing.expectError(
4145 error.ParseZon,4274 error.ParseZon,
4146 fromSliceAlloc(*const ?*const bool, .{4275 fromSlice(*const ?*const bool, .{
4147 .gpa = gpa,4276 .gpa = gpa,
4148 .arena = arena,4277 .arena = arena,
4149 .source = "10",4278 .source = "10",
...@@ -4151,16 +4280,16 @@ test "std.zon add pointers" {...@@ -4151,16 +4280,16 @@ test "std.zon add pointers" {
4151 }),4280 }),
4152 );4281 );
4153 try std.testing.expectFmt(4282 try std.testing.expectFmt(
4283 \\input.zon: error.ParseZon
4154 \\input.zon:1:1: error: expected type '?bool'4284 \\input.zon:1:1: error: expected type '?bool'
4155 \\4285 \\
4156 , "{f}", .{errors.fmt("input.zon")});4286 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4157 }4287 }
41584288
4159 {4289 {
4160 var errors: Errors = .init(arena);
4161 try std.testing.expectError(4290 try std.testing.expectError(
4162 error.ParseZon,4291 error.ParseZon,
4163 fromSliceAlloc(*const ?*const struct { a: i32 }, .{4292 fromSlice(*const ?*const struct { a: i32 }, .{
4164 .gpa = gpa,4293 .gpa = gpa,
4165 .arena = arena,4294 .arena = arena,
4166 .source = "true",4295 .source = "true",
...@@ -4168,16 +4297,16 @@ test "std.zon add pointers" {...@@ -4168,16 +4297,16 @@ test "std.zon add pointers" {
4168 }),4297 }),
4169 );4298 );
4170 try std.testing.expectFmt(4299 try std.testing.expectFmt(
4300 \\input.zon: error.ParseZon
4171 \\input.zon:1:1: error: expected optional struct4301 \\input.zon:1:1: error: expected optional struct
4172 \\4302 \\
4173 , "{f}", .{errors.fmt("input.zon")});4303 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4174 }4304 }
41754305
4176 {4306 {
4177 var errors: Errors = .init(arena);
4178 try std.testing.expectError(4307 try std.testing.expectError(
4179 error.ParseZon,4308 error.ParseZon,
4180 fromSliceAlloc(*const ?*const struct { i32 }, .{4309 fromSlice(*const ?*const struct { i32 }, .{
4181 .gpa = gpa,4310 .gpa = gpa,
4182 .arena = arena,4311 .arena = arena,
4183 .source = "true",4312 .source = "true",
...@@ -4185,16 +4314,16 @@ test "std.zon add pointers" {...@@ -4185,16 +4314,16 @@ test "std.zon add pointers" {
4185 }),4314 }),
4186 );4315 );
4187 try std.testing.expectFmt(4316 try std.testing.expectFmt(
4317 \\input.zon: error.ParseZon
4188 \\input.zon:1:1: error: expected optional tuple4318 \\input.zon:1:1: error: expected optional tuple
4189 \\4319 \\
4190 , "{f}", .{errors.fmt("input.zon")});4320 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4191 }4321 }
41924322
4193 {4323 {
4194 var errors: Errors = .init(arena);
4195 try std.testing.expectError(4324 try std.testing.expectError(
4196 error.ParseZon,4325 error.ParseZon,
4197 fromSliceAlloc(*const ?*const union { x: void }, .{4326 fromSlice(*const ?*const union { x: void }, .{
4198 .gpa = gpa,4327 .gpa = gpa,
4199 .arena = arena,4328 .arena = arena,
4200 .source = "true",4329 .source = "true",
...@@ -4202,16 +4331,16 @@ test "std.zon add pointers" {...@@ -4202,16 +4331,16 @@ test "std.zon add pointers" {
4202 }),4331 }),
4203 );4332 );
4204 try std.testing.expectFmt(4333 try std.testing.expectFmt(
4334 \\input.zon: error.ParseZon
4205 \\input.zon:1:1: error: expected optional union4335 \\input.zon:1:1: error: expected optional union
4206 \\4336 \\
4207 , "{f}", .{errors.fmt("input.zon")});4337 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4208 }4338 }
42094339
4210 {4340 {
4211 var errors: Errors = .init(arena);
4212 try std.testing.expectError(4341 try std.testing.expectError(
4213 error.ParseZon,4342 error.ParseZon,
4214 fromSliceAlloc(*const ?*const [3]u8, .{4343 fromSlice(*const ?*const [3]u8, .{
4215 .gpa = gpa,4344 .gpa = gpa,
4216 .arena = arena,4345 .arena = arena,
4217 .source = "true",4346 .source = "true",
...@@ -4219,16 +4348,16 @@ test "std.zon add pointers" {...@@ -4219,16 +4348,16 @@ test "std.zon add pointers" {
4219 }),4348 }),
4220 );4349 );
4221 try std.testing.expectFmt(4350 try std.testing.expectFmt(
4351 \\input.zon: error.ParseZon
4222 \\input.zon:1:1: error: expected optional array4352 \\input.zon:1:1: error: expected optional array
4223 \\4353 \\
4224 , "{f}", .{errors.fmt("input.zon")});4354 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4225 }4355 }
42264356
4227 {4357 {
4228 var errors: Errors = .init(arena);
4229 try std.testing.expectError(4358 try std.testing.expectError(
4230 error.ParseZon,4359 error.ParseZon,
4231 fromSliceAlloc(?[3]u8, .{4360 fromSlice(?[3]u8, .{
4232 .gpa = gpa,4361 .gpa = gpa,
4233 .arena = arena,4362 .arena = arena,
4234 .source = "true",4363 .source = "true",
...@@ -4236,16 +4365,16 @@ test "std.zon add pointers" {...@@ -4236,16 +4365,16 @@ test "std.zon add pointers" {
4236 }),4365 }),
4237 );4366 );
4238 try std.testing.expectFmt(4367 try std.testing.expectFmt(
4368 \\input.zon: error.ParseZon
4239 \\input.zon:1:1: error: expected optional array4369 \\input.zon:1:1: error: expected optional array
4240 \\4370 \\
4241 , "{f}", .{errors.fmt("input.zon")});4371 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4242 }4372 }
42434373
4244 {4374 {
4245 var errors: Errors = .init(arena);
4246 try std.testing.expectError(4375 try std.testing.expectError(
4247 error.ParseZon,4376 error.ParseZon,
4248 fromSliceAlloc(*const ?*const []u8, .{4377 fromSlice(*const ?*const []u8, .{
4249 .gpa = gpa,4378 .gpa = gpa,
4250 .arena = arena,4379 .arena = arena,
4251 .source = "true",4380 .source = "true",
...@@ -4253,16 +4382,16 @@ test "std.zon add pointers" {...@@ -4253,16 +4382,16 @@ test "std.zon add pointers" {
4253 }),4382 }),
4254 );4383 );
4255 try std.testing.expectFmt(4384 try std.testing.expectFmt(
4385 \\input.zon: error.ParseZon
4256 \\input.zon:1:1: error: expected optional array4386 \\input.zon:1:1: error: expected optional array
4257 \\4387 \\
4258 , "{f}", .{errors.fmt("input.zon")});4388 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4259 }4389 }
42604390
4261 {4391 {
4262 var errors: Errors = .init(arena);
4263 try std.testing.expectError(4392 try std.testing.expectError(
4264 error.ParseZon,4393 error.ParseZon,
4265 fromSliceAlloc(?[]u8, .{4394 fromSlice(?[]u8, .{
4266 .gpa = gpa,4395 .gpa = gpa,
4267 .arena = arena,4396 .arena = arena,
4268 .source = "true",4397 .source = "true",
...@@ -4270,16 +4399,16 @@ test "std.zon add pointers" {...@@ -4270,16 +4399,16 @@ test "std.zon add pointers" {
4270 }),4399 }),
4271 );4400 );
4272 try std.testing.expectFmt(4401 try std.testing.expectFmt(
4402 \\input.zon: error.ParseZon
4273 \\input.zon:1:1: error: expected optional array4403 \\input.zon:1:1: error: expected optional array
4274 \\4404 \\
4275 , "{f}", .{errors.fmt("input.zon")});4405 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4276 }4406 }
42774407
4278 {4408 {
4279 var errors: Errors = .init(arena);
4280 try std.testing.expectError(4409 try std.testing.expectError(
4281 error.ParseZon,4410 error.ParseZon,
4282 fromSliceAlloc(*const ?*const []const u8, .{4411 fromSlice(*const ?*const []const u8, .{
4283 .gpa = gpa,4412 .gpa = gpa,
4284 .arena = arena,4413 .arena = arena,
4285 .source = "true",4414 .source = "true",
...@@ -4287,16 +4416,16 @@ test "std.zon add pointers" {...@@ -4287,16 +4416,16 @@ test "std.zon add pointers" {
4287 }),4416 }),
4288 );4417 );
4289 try std.testing.expectFmt(4418 try std.testing.expectFmt(
4419 \\input.zon: error.ParseZon
4290 \\input.zon:1:1: error: expected optional string4420 \\input.zon:1:1: error: expected optional string
4291 \\4421 \\
4292 , "{f}", .{errors.fmt("input.zon")});4422 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4293 }4423 }
42944424
4295 {4425 {
4296 var errors: Errors = .init(arena);
4297 try std.testing.expectError(4426 try std.testing.expectError(
4298 error.ParseZon,4427 error.ParseZon,
4299 fromSliceAlloc(*const ?*const enum { foo }, .{4428 fromSlice(*const ?*const enum { foo }, .{
4300 .gpa = gpa,4429 .gpa = gpa,
4301 .arena = arena,4430 .arena = arena,
4302 .source = "true",4431 .source = "true",
...@@ -4304,14 +4433,19 @@ test "std.zon add pointers" {...@@ -4304,14 +4433,19 @@ test "std.zon add pointers" {
4304 }),4433 }),
4305 );4434 );
4306 try std.testing.expectFmt(4435 try std.testing.expectFmt(
4436 \\input.zon: error.ParseZon
4307 \\input.zon:1:1: error: expected optional enum literal4437 \\input.zon:1:1: error: expected optional enum literal
4308 \\4438 \\
4309 , "{f}", .{errors.fmt("input.zon")});4439 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4310 }4440 }
4311}4441}
43124442
4313test "std.zon stop on node" {4443test "std.zon stop on node" {
4314 const gpa = std.testing.allocator;4444 const gpa = std.testing.allocator;
4445 var arena_allocator: ArenaAllocator = .init(gpa);
4446 defer arena_allocator.deinit();
4447 const arena = arena_allocator.allocator();
4448 var errors: Errors = .empty;
43154449
4316 {4450 {
4317 const Vec2 = struct {4451 const Vec2 = struct {
...@@ -4325,10 +4459,11 @@ test "std.zon stop on node" {...@@ -4325,10 +4459,11 @@ test "std.zon stop on node" {
4325 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });4459 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
4326 defer zoir.deinit(gpa);4460 defer zoir.deinit(gpa);
43274461
4328 const result = try fromZoir(Vec2, .{4462 const result = try fromZoirNoAlloc(Vec2, .{
4463 .arena = arena,
4329 .ast = &ast,4464 .ast = &ast,
4330 .zoir = &zoir,4465 .zoir = &zoir,
4331 .errors = null,4466 .errors = &errors,
4332 });4467 });
43334468
4334 try std.testing.expectEqual(result.y, 2.5);4469 try std.testing.expectEqual(result.y, 2.5);
...@@ -4342,10 +4477,11 @@ test "std.zon stop on node" {...@@ -4342,10 +4477,11 @@ test "std.zon stop on node" {
4342 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });4477 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
4343 defer zoir.deinit(gpa);4478 defer zoir.deinit(gpa);
43444479
4345 const result = try fromZoir(Zoir.Node.Index, .{4480 const result = try fromZoirNoAlloc(Zoir.Node.Index, .{
4481 .arena = arena,
4346 .ast = &ast,4482 .ast = &ast,
4347 .zoir = &zoir,4483 .zoir = &zoir,
4348 .errors = null,4484 .errors = &errors,
4349 });4485 });
4350 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(&zoir));4486 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(&zoir));
4351 }4487 }
...@@ -4353,13 +4489,18 @@ test "std.zon stop on node" {...@@ -4353,13 +4489,18 @@ test "std.zon stop on node" {
43534489
4354test "std.zon no alloc" {4490test "std.zon no alloc" {
4355 const gpa = std.testing.allocator;4491 const gpa = std.testing.allocator;
4492 var arena_allocator: ArenaAllocator = .init(gpa);
4493 defer arena_allocator.deinit();
4494 const arena = arena_allocator.allocator();
4495 var errors: Errors = .empty;
43564496
4357 try std.testing.expectEqual(4497 try std.testing.expectEqual(
4358 [3]u8{ 1, 2, 3 },4498 [3]u8{ 1, 2, 3 },
4359 try fromSlice([3]u8, .{4499 try fromSliceNoAlloc([3]u8, .{
4360 .gpa = gpa,4500 .gpa = gpa,
4501 .arena = arena,
4361 .source = ".{ 1, 2, 3 }",4502 .source = ".{ 1, 2, 3 }",
4362 .errors = null,4503 .errors = &errors,
4363 }),4504 }),
4364 );4505 );
43654506
...@@ -4373,10 +4514,11 @@ test "std.zon no alloc" {...@@ -4373,10 +4514,11 @@ test "std.zon no alloc" {
43734514
4374 try std.testing.expectEqual(4515 try std.testing.expectEqual(
4375 Nested{ 1, 2, .{ 3, 4 } },4516 Nested{ 1, 2, .{ 3, 4 } },
4376 try fromZoir(Nested, .{4517 try fromZoirNoAlloc(Nested, .{
4518 .arena = arena,
4377 .ast = &ast,4519 .ast = &ast,
4378 .zoir = &zoir,4520 .zoir = &zoir,
4379 .errors = null,4521 .errors = &errors,
4380 }),4522 }),
4381 );4523 );
4382}4524}
...@@ -4386,44 +4528,45 @@ test "std.zon errors without errorsnostics" {...@@ -4386,44 +4528,45 @@ test "std.zon errors without errorsnostics" {
4386 var arena_allocator: ArenaAllocator = .init(gpa);4528 var arena_allocator: ArenaAllocator = .init(gpa);
4387 defer arena_allocator.deinit();4529 defer arena_allocator.deinit();
4388 const arena = arena_allocator.allocator();4530 const arena = arena_allocator.allocator();
4531 var errors: Errors = .empty;
43894532
4390 const Enum = enum {4533 const Enum = enum {
4391 foo,4534 foo,
4392 bar,4535 bar,
4393 baz,4536 baz,
4394 };4537 };
4395 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Enum, .{4538 try std.testing.expectError(error.ParseZon, fromSlice(Enum, .{
4396 .gpa = gpa,4539 .gpa = gpa,
4397 .arena = arena,4540 .arena = arena,
4398 .source = ".nothing",4541 .source = ".nothing",
4399 .errors = null,4542 .errors = &errors,
4400 }));4543 }));
44014544
4402 const Struct = struct {4545 const Struct = struct {
4403 name: []const u8,4546 name: []const u8,
4404 };4547 };
4405 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{4548 try std.testing.expectError(error.ParseZon, fromSlice(Struct, .{
4406 .gpa = gpa,4549 .gpa = gpa,
4407 .arena = arena,4550 .arena = arena,
4408 .source = ".{ .name = \"Alice\", .age = 25 }",4551 .source = ".{ .name = \"Alice\", .age = 25 }",
4409 .errors = null,4552 .errors = &errors,
4410 }));4553 }));
44114554
4412 const Union = union(enum) {4555 const Union = union(enum) {
4413 x,4556 x,
4414 y: u32,4557 y: u32,
4415 };4558 };
4416 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{4559 try std.testing.expectError(error.ParseZon, fromSlice(Union, .{
4417 .gpa = gpa,4560 .gpa = gpa,
4418 .arena = arena,4561 .arena = arena,
4419 .source = ".a",4562 .source = ".a",
4420 .errors = null,4563 .errors = &errors,
4421 }));4564 }));
4422 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{4565 try std.testing.expectError(error.ParseZon, fromSlice(Union, .{
4423 .gpa = gpa,4566 .gpa = gpa,
4424 .arena = arena,4567 .arena = arena,
4425 .source = ".{ .b = 8 }",4568 .source = ".{ .b = 8 }",
4426 .errors = null,4569 .errors = &errors,
4427 }));4570 }));
4428}4571}
44294572
...@@ -4432,6 +4575,7 @@ test "std.zon aligned pointers" {...@@ -4432,6 +4575,7 @@ test "std.zon aligned pointers" {
4432 var arena_allocator: ArenaAllocator = .init(gpa);4575 var arena_allocator: ArenaAllocator = .init(gpa);
4433 defer arena_allocator.deinit();4576 defer arena_allocator.deinit();
4434 const arena = arena_allocator.allocator();4577 const arena = arena_allocator.allocator();
4578 var errors: Errors = .empty;
44354579
4436 const n: u8 align(8) = 10;4580 const n: u8 align(8) = 10;
4437 const Foo = struct {4581 const Foo = struct {
...@@ -4441,11 +4585,11 @@ test "std.zon aligned pointers" {...@@ -4441,11 +4585,11 @@ test "std.zon aligned pointers" {
4441 const expected: Foo = .{4585 const expected: Foo = .{
4442 .inner = &n,4586 .inner = &n,
4443 };4587 };
4444 const found = try fromSliceAlloc(Foo, .{4588 const found = try fromSlice(Foo, .{
4445 .gpa = gpa,4589 .gpa = gpa,
4446 .arena = arena,4590 .arena = arena,
4447 .source = ".{ .inner = 10 }",4591 .source = ".{ .inner = 10 }",
4448 .errors = null,4592 .errors = &errors,
4449 });4593 });
4450 try std.testing.expectEqualDeep(expected.inner, found.inner);4594 try std.testing.expectEqualDeep(expected.inner, found.inner);
4451}4595}
...@@ -4455,6 +4599,7 @@ test "std.zon update basic" {...@@ -4455,6 +4599,7 @@ test "std.zon update basic" {
4455 var arena_allocator: ArenaAllocator = .init(gpa);4599 var arena_allocator: ArenaAllocator = .init(gpa);
4456 defer arena_allocator.deinit();4600 defer arena_allocator.deinit();
4457 const arena = arena_allocator.allocator();4601 const arena = arena_allocator.allocator();
4602 var errors: Errors = .empty;
44584603
4459 const Vector = struct { x: f32, y: f32, z: f32 };4604 const Vector = struct { x: f32, y: f32, z: f32 };
4460 const MyStruct = struct {4605 const MyStruct = struct {
...@@ -4486,77 +4631,77 @@ test "std.zon update basic" {...@@ -4486,77 +4631,77 @@ test "std.zon update basic" {
4486 .str = "hello, world",4631 .str = "hello, world",
4487 };4632 };
44884633
4489 try updateFromSliceAlloc(MyStruct, &found, .{4634 try updateFromSlice(MyStruct, &found, .{
4490 .gpa = gpa,4635 .gpa = gpa,
4491 .arena = arena,4636 .arena = arena,
4492 .source = ".{}",4637 .source = ".{}",
4493 .errors = null,4638 .errors = &errors,
4494 });4639 });
4495 try std.testing.expectEqualDeep(expected, found);4640 try std.testing.expectEqualDeep(expected, found);
44964641
4497 try updateFromSliceAlloc(MyStruct, &found, .{4642 try updateFromSlice(MyStruct, &found, .{
4498 .gpa = gpa,4643 .gpa = gpa,
4499 .arena = arena,4644 .arena = arena,
4500 .source = ".{ .bar = false }",4645 .source = ".{ .bar = false }",
4501 .errors = null,4646 .errors = &errors,
4502 });4647 });
4503 expected.bar = false;4648 expected.bar = false;
4504 try std.testing.expectEqualDeep(expected, found);4649 try std.testing.expectEqualDeep(expected, found);
45054650
4506 try updateFromSliceAlloc(MyStruct, &found, .{4651 try updateFromSlice(MyStruct, &found, .{
4507 .gpa = gpa,4652 .gpa = gpa,
4508 .arena = arena,4653 .arena = arena,
4509 .source = ".{ .baz = .{ .a = .{ 2, 4 } } }",4654 .source = ".{ .baz = .{ .a = .{ 2, 4 } } }",
4510 .errors = null,4655 .errors = &errors,
4511 });4656 });
4512 expected.baz.a[0] = 2;4657 expected.baz.a[0] = 2;
4513 expected.baz.a[1] = 4;4658 expected.baz.a[1] = 4;
4514 try std.testing.expectEqualDeep(expected, found);4659 try std.testing.expectEqualDeep(expected, found);
45154660
4516 try updateFromSliceAlloc(MyStruct, &found, .{4661 try updateFromSlice(MyStruct, &found, .{
4517 .gpa = gpa,4662 .gpa = gpa,
4518 .arena = arena,4663 .arena = arena,
4519 .source = ".{ .foo = 11, .baz = .{ .b = .d } }",4664 .source = ".{ .foo = 11, .baz = .{ .b = .d } }",
4520 .errors = null,4665 .errors = &errors,
4521 });4666 });
4522 expected.foo = 11;4667 expected.foo = 11;
4523 expected.baz.b = .d;4668 expected.baz.b = .d;
4524 try std.testing.expectEqualDeep(expected, found);4669 try std.testing.expectEqualDeep(expected, found);
45254670
4526 try updateFromSliceAlloc(MyStruct, &found, .{4671 try updateFromSlice(MyStruct, &found, .{
4527 .gpa = gpa,4672 .gpa = gpa,
4528 .arena = arena,4673 .arena = arena,
4529 .source = ".{ .optional = 10 }",4674 .source = ".{ .optional = 10 }",
4530 .errors = null,4675 .errors = &errors,
4531 });4676 });
4532 expected.optional = 10;4677 expected.optional = 10;
4533 try std.testing.expectEqualDeep(expected, found);4678 try std.testing.expectEqualDeep(expected, found);
45344679
4535 try updateFromSliceAlloc(MyStruct, &found, .{4680 try updateFromSlice(MyStruct, &found, .{
4536 .gpa = gpa,4681 .gpa = gpa,
4537 .arena = arena,4682 .arena = arena,
4538 .source = ".{ .optional = null }",4683 .source = ".{ .optional = null }",
4539 .errors = null,4684 .errors = &errors,
4540 });4685 });
4541 expected.optional = null;4686 expected.optional = null;
4542 try std.testing.expectEqualDeep(expected, found);4687 try std.testing.expectEqualDeep(expected, found);
45434688
4544 try updateFromSliceAlloc(MyStruct, &found, .{4689 try updateFromSlice(MyStruct, &found, .{
4545 .gpa = gpa,4690 .gpa = gpa,
4546 .arena = arena,4691 .arena = arena,
4547 .source = ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",4692 .source = ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",
4548 .errors = null,4693 .errors = &errors,
4549 });4694 });
4550 expected.ptr.x = 10;4695 expected.ptr.x = 10;
4551 expected.ptr.y = 20;4696 expected.ptr.y = 20;
4552 expected.ptr.z = 30;4697 expected.ptr.z = 30;
4553 try std.testing.expectEqualDeep(expected, found);4698 try std.testing.expectEqualDeep(expected, found);
45544699
4555 try updateFromSliceAlloc(MyStruct, &found, .{4700 try updateFromSlice(MyStruct, &found, .{
4556 .gpa = gpa,4701 .gpa = gpa,
4557 .arena = arena,4702 .arena = arena,
4558 .source = ".{ .str = \"foo\" }",4703 .source = ".{ .str = \"foo\" }",
4559 .errors = null,4704 .errors = &errors,
4560 });4705 });
4561 expected.str = "foo";4706 expected.str = "foo";
4562 try std.testing.expectEqualDeep(expected, found);4707 try std.testing.expectEqualDeep(expected, found);
...@@ -4567,6 +4712,7 @@ test "std.zon update optionals" {...@@ -4567,6 +4712,7 @@ test "std.zon update optionals" {
4567 var arena_allocator: ArenaAllocator = .init(gpa);4712 var arena_allocator: ArenaAllocator = .init(gpa);
4568 defer arena_allocator.deinit();4713 defer arena_allocator.deinit();
4569 const arena = arena_allocator.allocator();4714 const arena = arena_allocator.allocator();
4715 var errors: Errors = .empty;
45704716
4571 const MyStruct = struct {4717 const MyStruct = struct {
4572 foo: ?struct { bar: u32 = 1, baz: u32 = 2, qux: u32 },4718 foo: ?struct { bar: u32 = 1, baz: u32 = 2, qux: u32 },
...@@ -4576,10 +4722,11 @@ test "std.zon update optionals" {...@@ -4576,10 +4722,11 @@ test "std.zon update optionals" {
4576 {4722 {
4577 var expected: MyStruct = .{ .foo = null };4723 var expected: MyStruct = .{ .foo = null };
4578 var found = expected;4724 var found = expected;
4579 try updateFromSlice(MyStruct, &found, .{4725 try updateFromSliceNoAlloc(MyStruct, &found, .{
4580 .gpa = gpa,4726 .gpa = gpa,
4727 .arena = arena,
4581 .source = ".{ .foo = .{ .qux = 3 } }",4728 .source = ".{ .foo = .{ .qux = 3 } }",
4582 .errors = null,4729 .errors = &errors,
4583 });4730 });
4584 expected.foo = .{ .qux = 3 };4731 expected.foo = .{ .qux = 3 };
4585 try std.testing.expectEqual(expected, found);4732 try std.testing.expectEqual(expected, found);
...@@ -4588,16 +4735,17 @@ test "std.zon update optionals" {...@@ -4588,16 +4735,17 @@ test "std.zon update optionals" {
4588 // Updating an optional that starts out null should error if we leave off required fields.4735 // Updating an optional that starts out null should error if we leave off required fields.
4589 {4736 {
4590 var found: MyStruct = .{ .foo = null };4737 var found: MyStruct = .{ .foo = null };
4591 var errors: Errors = .init(arena);4738 try std.testing.expectError(error.ParseZon, updateFromSliceNoAlloc(MyStruct, &found, .{
4592 try std.testing.expectError(error.ParseZon, updateFromSlice(MyStruct, &found, .{
4593 .gpa = gpa,4739 .gpa = gpa,
4740 .arena = arena,
4594 .source = ".{ .foo = .{} }",4741 .source = ".{ .foo = .{} }",
4595 .errors = &errors,4742 .errors = &errors,
4596 }));4743 }));
4597 try std.testing.expectFmt(4744 try std.testing.expectFmt(
4745 \\input.zon: error.ParseZon
4598 \\input.zon:1:12: error: missing required field qux4746 \\input.zon:1:12: error: missing required field qux
4599 \\4747 \\
4600 , "{f}", .{errors.fmt("input.zon")});4748 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4601 }4749 }
46024750
4603 // Updating an optional that starts out non-null should preserve any values we leave off. It's4751 // Updating an optional that starts out non-null should preserve any values we leave off. It's
...@@ -4607,10 +4755,11 @@ test "std.zon update optionals" {...@@ -4607,10 +4755,11 @@ test "std.zon update optionals" {
4607 .foo = .{ .bar = 10, .baz = 20, .qux = 30 },4755 .foo = .{ .bar = 10, .baz = 20, .qux = 30 },
4608 };4756 };
4609 var found = expected;4757 var found = expected;
4610 try updateFromSlice(MyStruct, &found, .{4758 try updateFromSliceNoAlloc(MyStruct, &found, .{
4611 .gpa = gpa,4759 .gpa = gpa,
4760 .arena = arena,
4612 .source = ".{ .foo = .{ .baz = 200 } }",4761 .source = ".{ .foo = .{ .baz = 200 } }",
4613 .errors = null,4762 .errors = &errors,
4614 });4763 });
4615 expected.foo.?.baz = 200;4764 expected.foo.?.baz = 200;
4616 try std.testing.expectEqual(expected, found);4765 try std.testing.expectEqual(expected, found);
...@@ -4622,6 +4771,7 @@ test "std.zon update optional pointers" {...@@ -4622,6 +4771,7 @@ test "std.zon update optional pointers" {
4622 var arena_allocator: ArenaAllocator = .init(gpa);4771 var arena_allocator: ArenaAllocator = .init(gpa);
4623 defer arena_allocator.deinit();4772 defer arena_allocator.deinit();
4624 const arena = arena_allocator.allocator();4773 const arena = arena_allocator.allocator();
4774 var errors: Errors = .empty;
46254775
4626 const MyStruct = struct {4776 const MyStruct = struct {
4627 foo: ?*const struct { bar: u32 = 1, baz: u32 = 2, qux: u32 },4777 foo: ?*const struct { bar: u32 = 1, baz: u32 = 2, qux: u32 },
...@@ -4631,11 +4781,11 @@ test "std.zon update optional pointers" {...@@ -4631,11 +4781,11 @@ test "std.zon update optional pointers" {
4631 {4781 {
4632 var expected: MyStruct = .{ .foo = null };4782 var expected: MyStruct = .{ .foo = null };
4633 var found = expected;4783 var found = expected;
4634 try updateFromSliceAlloc(MyStruct, &found, .{4784 try updateFromSlice(MyStruct, &found, .{
4635 .gpa = gpa,4785 .gpa = gpa,
4636 .arena = arena,4786 .arena = arena,
4637 .source = ".{ .foo = .{ .qux = 3 } }",4787 .source = ".{ .foo = .{ .qux = 3 } }",
4638 .errors = null,4788 .errors = &errors,
4639 });4789 });
4640 expected.foo = &.{ .qux = 3 };4790 expected.foo = &.{ .qux = 3 };
4641 try std.testing.expectEqualDeep(expected, found);4791 try std.testing.expectEqualDeep(expected, found);
...@@ -4647,6 +4797,7 @@ test "std.zon update pointers" {...@@ -4647,6 +4797,7 @@ test "std.zon update pointers" {
4647 var arena_allocator: ArenaAllocator = .init(gpa);4797 var arena_allocator: ArenaAllocator = .init(gpa);
4648 defer arena_allocator.deinit();4798 defer arena_allocator.deinit();
4649 const arena = arena_allocator.allocator();4799 const arena = arena_allocator.allocator();
4800 var errors: Errors = .empty;
46504801
4651 // Updating a pointer should leave fields we don't specify unchanged4802 // Updating a pointer should leave fields we don't specify unchanged
4652 {4803 {
...@@ -4656,11 +4807,11 @@ test "std.zon update pointers" {...@@ -4656,11 +4807,11 @@ test "std.zon update pointers" {
4656 var ptr: @typeInfo(@FieldType(MyStruct, "foo")).pointer.child = .{ .qux = 3 };4807 var ptr: @typeInfo(@FieldType(MyStruct, "foo")).pointer.child = .{ .qux = 3 };
4657 var expected: MyStruct = .{ .foo = &ptr };4808 var expected: MyStruct = .{ .foo = &ptr };
4658 var found = expected;4809 var found = expected;
4659 try updateFromSliceAlloc(MyStruct, &found, .{4810 try updateFromSlice(MyStruct, &found, .{
4660 .gpa = gpa,4811 .gpa = gpa,
4661 .arena = arena,4812 .arena = arena,
4662 .source = ".{ .foo = .{ .bar = 100 } }",4813 .source = ".{ .foo = .{ .bar = 100 } }",
4663 .errors = null,4814 .errors = &errors,
4664 });4815 });
4665 expected.foo.bar = 100;4816 expected.foo.bar = 100;
4666 try std.testing.expectEqualDeep(expected, found);4817 try std.testing.expectEqualDeep(expected, found);
...@@ -4673,11 +4824,11 @@ test "std.zon update pointers" {...@@ -4673,11 +4824,11 @@ test "std.zon update pointers" {
4673 };4824 };
4674 var expected: MyStruct = .{ .foo = &.{ .qux = 3 } };4825 var expected: MyStruct = .{ .foo = &.{ .qux = 3 } };
4675 var found = expected;4826 var found = expected;
4676 try updateFromSliceAlloc(MyStruct, &found, .{4827 try updateFromSlice(MyStruct, &found, .{
4677 .gpa = gpa,4828 .gpa = gpa,
4678 .arena = arena,4829 .arena = arena,
4679 .source = ".{ .foo = .{ .bar = 100 } }",4830 .source = ".{ .foo = .{ .bar = 100 } }",
4680 .errors = null,4831 .errors = &errors,
4681 });4832 });
4682 expected.foo = &.{ .bar = 100, .baz = 20, .qux = 3 };4833 expected.foo = &.{ .bar = 100, .baz = 20, .qux = 3 };
4683 try std.testing.expectEqualDeep(expected, found);4834 try std.testing.expectEqualDeep(expected, found);
...@@ -4689,6 +4840,7 @@ test "std.zon update unions" {...@@ -4689,6 +4840,7 @@ test "std.zon update unions" {
4689 var arena_allocator: ArenaAllocator = .init(gpa);4840 var arena_allocator: ArenaAllocator = .init(gpa);
4690 defer arena_allocator.deinit();4841 defer arena_allocator.deinit();
4691 const arena = arena_allocator.allocator();4842 const arena = arena_allocator.allocator();
4843 var errors: Errors = .empty;
46924844
4693 const MyUnion = union(enum) {4845 const MyUnion = union(enum) {
4694 none: void,4846 none: void,
...@@ -4699,10 +4851,11 @@ test "std.zon update unions" {...@@ -4699,10 +4851,11 @@ test "std.zon update unions" {
4699 {4851 {
4700 var expected: MyUnion = .none;4852 var expected: MyUnion = .none;
4701 var found = expected;4853 var found = expected;
4702 try updateFromSlice(MyUnion, &found, .{4854 try updateFromSliceNoAlloc(MyUnion, &found, .{
4703 .gpa = gpa,4855 .gpa = gpa,
4856 .arena = arena,
4704 .source = ".{ .foo = .{ .qux = 3 } }",4857 .source = ".{ .foo = .{ .qux = 3 } }",
4705 .errors = null,4858 .errors = &errors,
4706 });4859 });
4707 expected = .{ .foo = .{ .qux = 3 } };4860 expected = .{ .foo = .{ .qux = 3 } };
4708 try std.testing.expectEqual(expected, found);4861 try std.testing.expectEqual(expected, found);
...@@ -4711,16 +4864,17 @@ test "std.zon update unions" {...@@ -4711,16 +4864,17 @@ test "std.zon update unions" {
4711 // Updating a union to a new field should error if we leave off required sub-fields4864 // Updating a union to a new field should error if we leave off required sub-fields
4712 {4865 {
4713 var found: MyUnion = .none;4866 var found: MyUnion = .none;
4714 var errors: Errors = .init(arena);4867 try std.testing.expectError(error.ParseZon, updateFromSliceNoAlloc(MyUnion, &found, .{
4715 try std.testing.expectError(error.ParseZon, updateFromSlice(MyUnion, &found, .{
4716 .gpa = gpa,4868 .gpa = gpa,
4869 .arena = arena,
4717 .source = ".{ .foo = .{} }",4870 .source = ".{ .foo = .{} }",
4718 .errors = &errors,4871 .errors = &errors,
4719 }));4872 }));
4720 try std.testing.expectFmt(4873 try std.testing.expectFmt(
4874 \\input.zon: error.ParseZon
4721 \\input.zon:1:12: error: missing required field qux4875 \\input.zon:1:12: error: missing required field qux
4722 \\4876 \\
4723 , "{f}", .{errors.fmt("input.zon")});4877 , "{f}", .{errors.fmt("input.zon", error.ParseZon)});
4724 }4878 }
47254879
4726 // Updating a union should preseve any sub-fields that we left off. It's also okay to leave off4880 // Updating a union should preseve any sub-fields that we left off. It's also okay to leave off
...@@ -4730,10 +4884,11 @@ test "std.zon update unions" {...@@ -4730,10 +4884,11 @@ test "std.zon update unions" {
4730 .foo = .{ .bar = 10, .baz = 20, .qux = 30 },4884 .foo = .{ .bar = 10, .baz = 20, .qux = 30 },
4731 };4885 };
4732 var found = expected;4886 var found = expected;
4733 try updateFromSlice(MyUnion, &found, .{4887 try updateFromSliceNoAlloc(MyUnion, &found, .{
4734 .gpa = gpa,4888 .gpa = gpa,
4889 .arena = arena,
4735 .source = ".{ .foo = .{ .baz = 200 } }",4890 .source = ".{ .foo = .{ .baz = 200 } }",
4736 .errors = null,4891 .errors = &errors,
4737 });4892 });
4738 expected.foo.baz = 200;4893 expected.foo.baz = 200;
4739 try std.testing.expectEqual(expected, found);4894 try std.testing.expectEqual(expected, found);
...@@ -4748,6 +4903,7 @@ test "std.zon variants" {...@@ -4748,6 +4903,7 @@ test "std.zon variants" {
4748 var arena_allocator: ArenaAllocator = .init(gpa);4903 var arena_allocator: ArenaAllocator = .init(gpa);
4749 defer arena_allocator.deinit();4904 defer arena_allocator.deinit();
4750 const arena = arena_allocator.allocator();4905 const arena = arena_allocator.allocator();
4906 var errors: Errors = .empty;
47514907
4752 const Struct = struct { a: u32, b: u32 };4908 const Struct = struct { a: u32, b: u32 };
4753 const start: Struct = .{ .a = 10, .b = 20 };4909 const start: Struct = .{ .a = 10, .b = 20 };
...@@ -4761,36 +4917,38 @@ test "std.zon variants" {...@@ -4761,36 +4917,38 @@ test "std.zon variants" {
4761 defer zoir.deinit(gpa);4917 defer zoir.deinit(gpa);
47624918
4763 var curr = start;4919 var curr = start;
4764 try updateFromSlice(Struct, &curr, .{4920 try updateFromSliceNoAlloc(Struct, &curr, .{
4765 .gpa = gpa,4921 .gpa = gpa,
4922 .arena = arena,
4766 .source = ".{ .a = 100 }",4923 .source = ".{ .a = 100 }",
4767 .errors = null,4924 .errors = &errors,
4768 });4925 });
4769 try std.testing.expectEqual(end, curr);4926 try std.testing.expectEqual(end, curr);
47704927
4771 curr = start;4928 curr = start;
4772 try updateFromSliceAlloc(Struct, &curr, .{4929 try updateFromSlice(Struct, &curr, .{
4773 .gpa = gpa,4930 .gpa = gpa,
4774 .arena = arena,4931 .arena = arena,
4775 .source = ".{ .a = 100 }",4932 .source = ".{ .a = 100 }",
4776 .errors = null,4933 .errors = &errors,
4777 });4934 });
4778 try std.testing.expectEqual(end, curr);4935 try std.testing.expectEqual(end, curr);
47794936
4780 curr = start;4937 curr = start;
4781 try updateFromZoir(Struct, &curr, .{4938 try updateFromZoirNoAlloc(Struct, &curr, .{
4939 .arena = arena,
4782 .ast = &ast,4940 .ast = &ast,
4783 .zoir = &zoir,4941 .zoir = &zoir,
4784 .errors = null,4942 .errors = &errors,
4785 });4943 });
4786 try std.testing.expectEqual(end, curr);4944 try std.testing.expectEqual(end, curr);
47874945
4788 curr = start;4946 curr = start;
4789 try updateFromZoirAlloc(Struct, &curr, .{4947 try updateFromZoir(Struct, &curr, .{
4790 .arena = arena,4948 .arena = arena,
4791 .ast = &ast,4949 .ast = &ast,
4792 .zoir = &zoir,4950 .zoir = &zoir,
4793 .errors = null,4951 .errors = &errors,
4794 });4952 });
4795 try std.testing.expectEqual(end, curr);4953 try std.testing.expectEqual(end, curr);
4796 }4954 }
...@@ -4804,35 +4962,37 @@ test "std.zon variants" {...@@ -4804,35 +4962,37 @@ test "std.zon variants" {
48044962
4805 try std.testing.expectEqual(4963 try std.testing.expectEqual(
4806 end,4964 end,
4807 try fromSlice(Struct, .{4965 try fromSliceNoAlloc(Struct, .{
4808 .gpa = gpa,4966 .gpa = gpa,
4967 .arena = arena,
4809 .source = ".{ .a = 100, .b = 20 }",4968 .source = ".{ .a = 100, .b = 20 }",
4810 .errors = null,4969 .errors = &errors,
4811 }),4970 }),
4812 );4971 );
4813 try std.testing.expectEqual(4972 try std.testing.expectEqual(
4814 end,4973 end,
4815 try fromSliceAlloc(Struct, .{4974 try fromSlice(Struct, .{
4816 .gpa = gpa,4975 .gpa = gpa,
4817 .arena = arena,4976 .arena = arena,
4818 .source = ".{ .a = 100, .b = 20 }",4977 .source = ".{ .a = 100, .b = 20 }",
4819 .errors = null,4978 .errors = &errors,
4820 }),4979 }),
4821 );4980 );
4822 try std.testing.expectEqual(4981 try std.testing.expectEqual(
4823 try fromZoir(Struct, .{4982 try fromZoirNoAlloc(Struct, .{
4983 .arena = arena,
4824 .ast = &ast,4984 .ast = &ast,
4825 .zoir = &zoir,4985 .zoir = &zoir,
4826 .errors = null,4986 .errors = &errors,
4827 }),4987 }),
4828 end,4988 end,
4829 );4989 );
4830 try std.testing.expectEqual(4990 try std.testing.expectEqual(
4831 try fromZoirAlloc(Struct, .{4991 try fromZoir(Struct, .{
4832 .arena = arena,4992 .arena = arena,
4833 .ast = &ast,4993 .ast = &ast,
4834 .zoir = &zoir,4994 .zoir = &zoir,
4835 .errors = null,4995 .errors = &errors,
4836 }),4996 }),
4837 end,4997 end,
4838 );4998 );