| ... | ... | @@ -94,8 +94,12 @@ pub const Error = struct { |
| 94 | 94 | /// Errors encountered while parsing ZON. See `log` and `fatal` for reporting errors to the user. |
| 95 | 95 | pub const Errors = struct { |
| 96 | 96 | items: []const Error, |
| 97 | oom: bool, |
| 97 | 98 | |
| 98 | | pub const empty: Errors = .{ .items = &.{} }; |
| 99 | pub const empty: Errors = .{ |
| 100 | .items = &.{}, |
| 101 | .oom = false, |
| 102 | }; |
| 99 | 103 | |
| 100 | 104 | /// Log the failure with `std.log.err`. |
| 101 | 105 | pub fn log(self: *const Errors, path: []const u8) void { |
| ... | ... | @@ -119,12 +123,9 @@ pub const Errors = struct { |
| 119 | 123 | .arena = arena, |
| 120 | 124 | .source = ".{ .foo = 1, .bar = 2 }", |
| 121 | 125 | .errors = &errors, |
| 122 | | }) catch |err| switch (err) { |
| 123 | | error.OutOfMemory => return error.OutOfMemory, |
| 124 | | error.ParseZon => b: { |
| 125 | | errors.log("input.zon"); |
| 126 | | break :b .{ .foo = 0, .bar = 0 }; |
| 127 | | }, |
| 126 | }) catch b: { |
| 127 | errors.log("input.zon"); |
| 128 | break :b .{ .foo = 0, .bar = 0 }; |
| 128 | 129 | }; |
| 129 | 130 | _ = parsed; |
| 130 | 131 | } |
| ... | ... | @@ -151,16 +152,14 @@ pub const Errors = struct { |
| 151 | 152 | .arena = arena, |
| 152 | 153 | .source = ".{ .foo = 1, .bar = 2 }", |
| 153 | 154 | .errors = &errors, |
| 154 | | }) catch |err| switch (err) { |
| 155 | | error.OutOfMemory => return error.OutOfMemory, |
| 156 | | error.ParseZon => errors.fatal("input.zon"), |
| 157 | | }; |
| 155 | }) catch errors.fatal("input.zon"); |
| 158 | 156 | _ = parsed; |
| 159 | 157 | } |
| 160 | 158 | |
| 161 | 159 | pub fn fmt(self: *const Errors, path: []const u8) Formatter { |
| 162 | 160 | return .{ |
| 163 | 161 | .items = self.items, |
| 162 | .oom = self.oom, |
| 164 | 163 | .path = path, |
| 165 | 164 | }; |
| 166 | 165 | } |
| ... | ... | @@ -168,8 +167,12 @@ pub const Errors = struct { |
| 168 | 167 | pub const Formatter = struct { |
| 169 | 168 | path: []const u8, |
| 170 | 169 | items: []const Error, |
| 170 | oom: bool, |
| 171 | 171 | |
| 172 | 172 | pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void { |
| 173 | if (self.oom) { |
| 174 | try w.print("{s}: out of memory", .{self.path}); |
| 175 | } |
| 173 | 176 | for (self.items) |e| { |
| 174 | 177 | try w.print("{s}:", .{self.path}); |
| 175 | 178 | try w.print("{d}:{d}: error: {s}\n", .{ |
| ... | ... | @@ -189,6 +192,11 @@ pub const Errors = struct { |
| 189 | 192 | } |
| 190 | 193 | } |
| 191 | 194 | }; |
| 195 | |
| 196 | fn checkOom(self: *Errors, result: anytype) @TypeOf(result) { |
| 197 | self.oom |= result == error.OutOfMemory; |
| 198 | return result; |
| 199 | } |
| 192 | 200 | }; |
| 193 | 201 | |
| 194 | 202 | pub const Options = struct { |
| ... | ... | @@ -238,12 +246,9 @@ test fromSlice { |
| 238 | 246 | .arena = arena, |
| 239 | 247 | .source = source, |
| 240 | 248 | .errors = &errors, |
| 241 | | }) catch |err| switch (err) { |
| 242 | | error.OutOfMemory => return err, |
| 243 | | error.ParseZon => { |
| 244 | | errors.log("texture_options.zon"); |
| 245 | | return err; |
| 246 | | }, |
| 249 | }) catch |err| { |
| 250 | errors.log("texture_options.zon"); |
| 251 | return err; |
| 247 | 252 | }; |
| 248 | 253 | |
| 249 | 254 | try std.testing.expectEqualDeep(TextureOptions{ |
| ... | ... | @@ -313,24 +318,18 @@ test updateFromSlice { |
| 313 | 318 | .arena = arena, |
| 314 | 319 | .source = global_config, |
| 315 | 320 | .errors = &errors, |
| 316 | | }) catch |err| switch (err) { |
| 317 | | error.OutOfMemory => return err, |
| 318 | | error.ParseZon => { |
| 319 | | errors.log("global_config.zon"); |
| 320 | | return err; |
| 321 | | }, |
| 321 | }) catch |err| { |
| 322 | errors.log("global_config.zon"); |
| 323 | return err; |
| 322 | 324 | }; |
| 323 | 325 | updateFromSlice(MyTextEditorConfig, &config, .{ |
| 324 | 326 | .gpa = gpa, |
| 325 | 327 | .arena = arena, |
| 326 | 328 | .source = project_config, |
| 327 | 329 | .errors = &errors, |
| 328 | | }) catch |err| switch (err) { |
| 329 | | error.OutOfMemory => return err, |
| 330 | | error.ParseZon => { |
| 331 | | errors.log("project_config.zon"); |
| 332 | | return err; |
| 333 | | }, |
| 330 | }) catch |err| { |
| 331 | errors.log("project_config.zon"); |
| 332 | return err; |
| 334 | 333 | }; |
| 335 | 334 | |
| 336 | 335 | try std.testing.expectEqualDeep(MyTextEditorConfig{ |
| ... | ... | @@ -358,23 +357,32 @@ fn fromSliceInner( |
| 358 | 357 | initialized: bool, |
| 359 | 358 | options: Options, |
| 360 | 359 | ) error{ OutOfMemory, ParseZon }!void { |
| 360 | options.errors.oom = false; |
| 361 | 361 | var errors: std.ArrayList(Error) = .empty; |
| 362 | 362 | defer options.errors.items = errors.items; |
| 363 | 363 | |
| 364 | | var ast = try std.zig.Ast.parse(options.gpa, options.source, .{ .mode = .zon }); |
| 364 | var ast = try options.errors.checkOom(std.zig.Ast.parse( |
| 365 | options.gpa, |
| 366 | options.source, |
| 367 | .{ .mode = .zon }, |
| 368 | )); |
| 365 | 369 | defer ast.deinit(options.gpa); |
| 366 | 370 | |
| 367 | | var zoir = try ZonGen.generate(options.gpa, ast, .{ .parse_str_lits = false }); |
| 371 | var zoir = try options.errors.checkOom(ZonGen.generate( |
| 372 | options.gpa, |
| 373 | ast, |
| 374 | .{ .parse_str_lits = false }, |
| 375 | )); |
| 368 | 376 | defer zoir.deinit(options.gpa); |
| 369 | 377 | |
| 370 | | try inner(T, value, initialized, .{ |
| 378 | try options.errors.checkOom(inner(T, value, initialized, .{ |
| 371 | 379 | .arena = options.arena, |
| 372 | 380 | .ast = &ast, |
| 373 | 381 | .zoir = &zoir, |
| 374 | 382 | .node = .root, |
| 375 | 383 | .errors = &errors, |
| 376 | 384 | .ignore_unknown_fields = options.ignore_unknown_fields, |
| 377 | | }); |
| 385 | })); |
| 378 | 386 | } |
| 379 | 387 | |
| 380 | 388 | pub const FromZoirOptions = struct { |
| ... | ... | @@ -431,15 +439,16 @@ fn fromZoirInner( |
| 431 | 439 | initialized: bool, |
| 432 | 440 | options: FromZoirOptions, |
| 433 | 441 | ) error{ OutOfMemory, ParseZon }!void { |
| 442 | options.errors.oom = false; |
| 434 | 443 | var errors: std.ArrayList(Error) = .empty; |
| 435 | 444 | defer options.errors.items = errors.items; |
| 436 | | return inner(T, value, initialized, .{ |
| 445 | return options.errors.checkOom(inner(T, value, initialized, .{ |
| 437 | 446 | .arena = options.arena, |
| 438 | 447 | .ast = options.ast, |
| 439 | 448 | .zoir = options.zoir, |
| 440 | 449 | .errors = &errors, |
| 441 | 450 | .ignore_unknown_fields = options.ignore_unknown_fields, |
| 442 | | }); |
| 451 | })); |
| 443 | 452 | } |
| 444 | 453 | |
| 445 | 454 | const InnerOptions = struct { |
| ... | ... | @@ -1441,17 +1450,38 @@ test "std.zon failure/oom formatting" { |
| 1441 | 1450 | var arena_allocator: ArenaAllocator = .init(gpa); |
| 1442 | 1451 | defer arena_allocator.deinit(); |
| 1443 | 1452 | const arena = arena_allocator.allocator(); |
| 1444 | | var errors: Errors = .empty; |
| 1445 | 1453 | |
| 1446 | | try std.testing.expectError(error.OutOfMemory, fromSlice([]const u8, .{ |
| 1447 | | .gpa = .failing, |
| 1448 | | .arena = arena, |
| 1449 | | .source = "\"foo\"", |
| 1450 | | .errors = &errors, |
| 1451 | | })); |
| 1452 | | try std.testing.expectFmt( |
| 1453 | | \\ |
| 1454 | | , "{f}", .{errors.fmt("input.zon")}); |
| 1454 | { |
| 1455 | var errors: Errors = .empty; |
| 1456 | try std.testing.expectError(error.OutOfMemory, fromSlice([]const u8, .{ |
| 1457 | .gpa = .failing, |
| 1458 | .arena = arena, |
| 1459 | .source = "\"foo\"", |
| 1460 | .errors = &errors, |
| 1461 | })); |
| 1462 | try std.testing.expectFmt( |
| 1463 | \\input.zon: out of memory |
| 1464 | , "{f}", .{errors.fmt("input.zon")}); |
| 1465 | } |
| 1466 | |
| 1467 | { |
| 1468 | var ast = try std.zig.Ast.parse(gpa, "\"foo\"", .{ .mode = .zon }); |
| 1469 | defer ast.deinit(gpa); |
| 1470 | |
| 1471 | var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false }); |
| 1472 | defer zoir.deinit(gpa); |
| 1473 | |
| 1474 | var errors: Errors = .empty; |
| 1475 | try std.testing.expectError(error.OutOfMemory, fromZoir([]const u8, .{ |
| 1476 | .arena = .failing, |
| 1477 | .ast = &ast, |
| 1478 | .zoir = &zoir, |
| 1479 | .errors = &errors, |
| 1480 | })); |
| 1481 | try std.testing.expectFmt( |
| 1482 | \\input.zon: out of memory |
| 1483 | , "{f}", .{errors.fmt("input.zon")}); |
| 1484 | } |
| 1455 | 1485 | } |
| 1456 | 1486 | |
| 1457 | 1487 | test "std.zon fromSlice syntax error" { |