diff options
| author | Mason Remaley <mason@anthropicstudios.com> | 2024-11-04 14:03:36 -0800 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2025-02-03 09:14:37 +0000 |
| commit | 13c6eb0d71b253cc55a667e33dbdd4932f3710f1 (patch) | |
| tree | 8c6eee3ffc63cb6b0ec8f6a4407af3a94a949c64 /test/src/Cases.zig | |
| parent | 953355ebeab881abff4a2c9315daa4fbb290d733 (diff) | |
| download | zig-13c6eb0d71b253cc55a667e33dbdd4932f3710f1.tar.gz zig-13c6eb0d71b253cc55a667e33dbdd4932f3710f1.zip | |
compiler,std: implement ZON support
This commit allows using ZON (Zig Object Notation) in a few ways.
* `@import` can be used to load ZON at comptime and convert it to a
normal Zig value. In this case, `@import` must have a result type.
* `std.zon.parse` can be used to parse ZON at runtime, akin to the
parsing logic in `std.json`.
* `std.zon.stringify` can be used to convert arbitrary data structures
to ZON at runtime, again akin to `std.json`.
Diffstat (limited to 'test/src/Cases.zig')
| -rw-r--r-- | test/src/Cases.zig | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/test/src/Cases.zig b/test/src/Cases.zig index b57a476e89..db1a564373 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -90,6 +90,11 @@ pub const Case = struct { link_libc: bool = false, pic: ?bool = null, pie: ?bool = null, + /// A list of imports to cache alongside the source file. + imports: []const []const u8 = &.{}, + /// Where to look for imports relative to the `cases_dir_path` given to + /// `lower_to_build_steps`. If null, file imports will assert. + import_path: ?[]const u8 = null, deps: std.ArrayList(DepModule), @@ -413,6 +418,7 @@ fn addFromDirInner( const pic = try manifest.getConfigForKeyAssertSingle("pic", ?bool); const pie = try manifest.getConfigForKeyAssertSingle("pie", ?bool); const emit_bin = try manifest.getConfigForKeyAssertSingle("emit_bin", bool); + const imports = try manifest.getConfigForKeyAlloc(ctx.arena, "imports", []const u8); if (manifest.type == .translate_c) { for (c_frontends) |c_frontend| { @@ -470,7 +476,7 @@ fn addFromDirInner( const next = ctx.cases.items.len; try ctx.cases.append(.{ .name = std.fs.path.stem(filename), - .target = resolved_target, + .import_path = std.fs.path.dirname(filename), .backend = backend, .updates = std.ArrayList(Cases.Update).init(ctx.cases.allocator), .emit_bin = emit_bin, @@ -480,6 +486,8 @@ fn addFromDirInner( .pic = pic, .pie = pie, .deps = std.ArrayList(DepModule).init(ctx.cases.allocator), + .imports = imports, + .target = resolved_target, }); try cases.append(next); } @@ -619,6 +627,7 @@ pub fn lowerToBuildSteps( ) void { const host = std.zig.system.resolveTargetQuery(.{}) catch |err| std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)}); + const cases_dir_path = b.build_root.join(b.allocator, &.{ "test", "cases" }) catch @panic("OOM"); for (self.incremental_cases.items) |incr_case| { if (true) { @@ -662,11 +671,21 @@ pub fn lowerToBuildSteps( file_sources.put(file.path, writefiles.add(file.path, file.src)) catch @panic("OOM"); } + for (case.imports) |import_rel| { + const import_abs = std.fs.path.join(b.allocator, &.{ + cases_dir_path, + case.import_path orelse @panic("import_path not set"), + import_rel, + }) catch @panic("OOM"); + _ = writefiles.addCopyFile(.{ .cwd_relative = import_abs }, import_rel); + } + const mod = b.createModule(.{ .root_source_file = root_source_file, .target = case.target, .optimize = case.optimize_mode, }); + if (case.link_libc) mod.link_libc = true; if (case.pic) |pic| mod.pic = pic; for (case.deps.items) |dep| { @@ -962,6 +981,8 @@ const TestManifestConfigDefaults = struct { return "null"; } else if (std.mem.eql(u8, key, "pie")) { return "null"; + } else if (std.mem.eql(u8, key, "imports")) { + return ""; } else unreachable; } }; @@ -998,6 +1019,7 @@ const TestManifest = struct { .{ "backend", {} }, .{ "pic", {} }, .{ "pie", {} }, + .{ "imports", {} }, }); const Type = enum { @@ -1020,7 +1042,7 @@ const TestManifest = struct { fn ConfigValueIterator(comptime T: type) type { return struct { - inner: std.mem.SplitIterator(u8, .scalar), + inner: std.mem.TokenIterator(u8, .scalar), fn next(self: *@This()) !?T { const next_raw = self.inner.next() orelse return null; @@ -1098,7 +1120,9 @@ const TestManifest = struct { // Parse key=value(s) var kv_it = std.mem.splitScalar(u8, trimmed, '='); const key = kv_it.first(); - if (!valid_keys.has(key)) return error.InvalidKey; + if (!valid_keys.has(key)) { + return error.InvalidKey; + } try manifest.config_map.putNoClobber(key, kv_it.next() orelse return error.MissingValuesForConfig); } @@ -1115,7 +1139,7 @@ const TestManifest = struct { ) ConfigValueIterator(T) { const bytes = self.config_map.get(key) orelse TestManifestConfigDefaults.get(self.type, key); return ConfigValueIterator(T){ - .inner = std.mem.splitScalar(u8, bytes, ','), + .inner = std.mem.tokenizeScalar(u8, bytes, ','), }; } @@ -1232,6 +1256,18 @@ const TestManifest = struct { return try getDefaultParser(o.child)(str); } }.parse, + .@"struct" => @compileError("no default parser for " ++ @typeName(T)), + .pointer => { + if (T == []const u8) { + return struct { + fn parse(str: []const u8) anyerror!T { + return str; + } + }.parse; + } else { + @compileError("no default parser for " ++ @typeName(T)); + } + }, else => @compileError("no default parser for " ++ @typeName(T)), } } |
