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 /src/Zcu.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 'src/Zcu.zig')
| -rw-r--r-- | src/Zcu.zig | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/Zcu.zig b/src/Zcu.zig index 74653bce01..507452dda3 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -39,6 +39,8 @@ const AnalUnit = InternPool.AnalUnit; const BuiltinFn = std.zig.BuiltinFn; const LlvmObject = @import("codegen/llvm.zig").Object; const dev = @import("dev.zig"); +const Zoir = std.zig.Zoir; +const ZonGen = std.zig.ZonGen; comptime { @setEvalBranchQuota(4000); @@ -672,6 +674,8 @@ pub const File = struct { tree: Ast, /// Whether this is populated or not depends on `zir_loaded`. zir: Zir, + /// Cached Zoir, generated lazily. + zoir: ?Zoir = null, /// Module that this file is a part of, managed externally. mod: *Package.Module, /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen. @@ -704,7 +708,19 @@ pub const File = struct { root: *Package.Module, }; + pub fn getMode(self: File) Ast.Mode { + if (std.mem.endsWith(u8, self.sub_file_path, ".zon")) { + return .zon; + } else if (std.mem.endsWith(u8, self.sub_file_path, ".zig")) { + return .zig; + } else { + // `Module.importFile` rejects all other extensions + unreachable; + } + } + pub fn unload(file: *File, gpa: Allocator) void { + if (file.zoir) |zoir| zoir.deinit(gpa); file.unloadTree(gpa); file.unloadSource(gpa); file.unloadZir(gpa); @@ -778,11 +794,24 @@ pub const File = struct { if (file.tree_loaded) return &file.tree; const source = try file.getSource(gpa); - file.tree = try Ast.parse(gpa, source.bytes, .zig); + file.tree = try Ast.parse(gpa, source.bytes, file.getMode()); file.tree_loaded = true; return &file.tree; } + pub fn getZoir(file: *File, zcu: *Zcu) !*const Zoir { + if (file.zoir) |*zoir| return zoir; + + assert(file.tree_loaded); + assert(file.tree.mode == .zon); + file.zoir = try ZonGen.generate(zcu.gpa, file.tree, .{}); + if (file.zoir.?.hasCompileErrors()) { + try zcu.failed_files.putNoClobber(zcu.gpa, file, null); + return error.AnalysisFail; + } + return &file.zoir.?; + } + pub fn fullyQualifiedNameLen(file: File) usize { const ext = std.fs.path.extension(file.sub_file_path); return file.sub_file_path.len - ext.len; @@ -895,6 +924,7 @@ pub const File = struct { pub const Index = InternPool.FileIndex; }; +/// Represents the contents of a file loaded with `@embedFile`. pub const EmbedFile = struct { /// Module that this file is a part of, managed externally. owner: *Package.Module, @@ -2372,6 +2402,12 @@ pub const LazySrcLoc = struct { break :inst .{ info.file, info.inst }; }; const file = zcu.fileByIndex(file_index); + + // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR, + // which may not exist e.g. in the case of errors in ZON files. + if (zir_inst == .main_struct_inst) return .{ file, 0 }; + + // Otherwise, make sure ZIR is loaded. assert(file.zir_loaded); const zir = file.zir; @@ -3461,8 +3497,6 @@ pub fn atomicPtrAlignment( } /// Returns null in the following cases: -/// * `@TypeOf(.{})` -/// * A struct which has no fields (`struct {}`). /// * Not a struct. pub fn typeToStruct(zcu: *const Zcu, ty: Type) ?InternPool.LoadedStructType { if (ty.ip_index == .none) return null; |
