Skip to content

Commit 60935de

Browse files
authored
Merge pull request #14523 from ziglang/zon
introduce Zig Object Notation and use it for the build manifest file (build.zig.zon)
2 parents 4c7f828 + 81c27c7 commit 60935de

15 files changed

+4561
-4098
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ set(ZIG_STAGE2_SOURCES
513513
"${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig"
514514
"${CMAKE_SOURCE_DIR}/lib/std/zig/CrossTarget.zig"
515515
"${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig"
516-
"${CMAKE_SOURCE_DIR}/lib/std/zig/parse.zig"
516+
"${CMAKE_SOURCE_DIR}/lib/std/zig/Parse.zig"
517517
"${CMAKE_SOURCE_DIR}/lib/std/zig/render.zig"
518518
"${CMAKE_SOURCE_DIR}/lib/std/zig/string_literal.zig"
519519
"${CMAKE_SOURCE_DIR}/lib/std/zig/system.zig"

lib/std/Build.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,8 +1496,8 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
14961496
}
14971497
}
14981498

1499-
const full_path = b.pathFromRoot("build.zig.ini");
1500-
std.debug.print("no dependency named '{s}' in '{s}'\n", .{ name, full_path });
1499+
const full_path = b.pathFromRoot("build.zig.zon");
1500+
std.debug.print("no dependency named '{s}' in '{s}'. All packages used in build.zig must be declared in this file.\n", .{ name, full_path });
15011501
std.process.exit(1);
15021502
}
15031503

lib/std/Build/OptionsStep.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,5 +367,5 @@ test "OptionsStep" {
367367
\\
368368
, options.contents.items);
369369

370-
_ = try std.zig.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(0));
370+
_ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(0), .zig);
371371
}

lib/std/array_hash_map.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,8 @@ pub fn ArrayHashMapUnmanaged(
11451145
}
11461146

11471147
/// Create a copy of the hash map which can be modified separately.
1148-
/// The copy uses the same context and allocator as this instance.
1148+
/// The copy uses the same context as this instance, but is allocated
1149+
/// with the provided allocator.
11491150
pub fn clone(self: Self, allocator: Allocator) !Self {
11501151
if (@sizeOf(ByIndexContext) != 0)
11511152
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call cloneContext instead.");

lib/std/zig.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub const Tokenizer = tokenizer.Tokenizer;
88
pub const fmtId = fmt.fmtId;
99
pub const fmtEscapes = fmt.fmtEscapes;
1010
pub const isValidId = fmt.isValidId;
11-
pub const parse = @import("zig/parse.zig").parse;
1211
pub const string_literal = @import("zig/string_literal.zig");
1312
pub const number_literal = @import("zig/number_literal.zig");
1413
pub const primitives = @import("zig/primitives.zig");

lib/std/zig/Ast.zig

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
//! Abstract Syntax Tree for Zig source code.
2+
//! For Zig syntax, the root node is at nodes[0] and contains the list of
3+
//! sub-nodes.
4+
//! For Zon syntax, the root node is at nodes[0] and contains lhs as the node
5+
//! index of the main expression.
26

37
/// Reference to externally-owned data.
48
source: [:0]const u8,
@@ -11,13 +15,6 @@ extra_data: []Node.Index,
1115

1216
errors: []const Error,
1317

14-
const std = @import("../std.zig");
15-
const assert = std.debug.assert;
16-
const testing = std.testing;
17-
const mem = std.mem;
18-
const Token = std.zig.Token;
19-
const Ast = @This();
20-
2118
pub const TokenIndex = u32;
2219
pub const ByteOffset = u32;
2320

@@ -34,7 +31,7 @@ pub const Location = struct {
3431
line_end: usize,
3532
};
3633

37-
pub fn deinit(tree: *Ast, gpa: mem.Allocator) void {
34+
pub fn deinit(tree: *Ast, gpa: Allocator) void {
3835
tree.tokens.deinit(gpa);
3936
tree.nodes.deinit(gpa);
4037
gpa.free(tree.extra_data);
@@ -48,11 +45,69 @@ pub const RenderError = error{
4845
OutOfMemory,
4946
};
5047

48+
pub const Mode = enum { zig, zon };
49+
50+
/// Result should be freed with tree.deinit() when there are
51+
/// no more references to any of the tokens or nodes.
52+
pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!Ast {
53+
var tokens = Ast.TokenList{};
54+
defer tokens.deinit(gpa);
55+
56+
// Empirically, the zig std lib has an 8:1 ratio of source bytes to token count.
57+
const estimated_token_count = source.len / 8;
58+
try tokens.ensureTotalCapacity(gpa, estimated_token_count);
59+
60+
var tokenizer = std.zig.Tokenizer.init(source);
61+
while (true) {
62+
const token = tokenizer.next();
63+
try tokens.append(gpa, .{
64+
.tag = token.tag,
65+
.start = @intCast(u32, token.loc.start),
66+
});
67+
if (token.tag == .eof) break;
68+
}
69+
70+
var parser: Parse = .{
71+
.source = source,
72+
.gpa = gpa,
73+
.token_tags = tokens.items(.tag),
74+
.token_starts = tokens.items(.start),
75+
.errors = .{},
76+
.nodes = .{},
77+
.extra_data = .{},
78+
.scratch = .{},
79+
.tok_i = 0,
80+
};
81+
defer parser.errors.deinit(gpa);
82+
defer parser.nodes.deinit(gpa);
83+
defer parser.extra_data.deinit(gpa);
84+
defer parser.scratch.deinit(gpa);
85+
86+
// Empirically, Zig source code has a 2:1 ratio of tokens to AST nodes.
87+
// Make sure at least 1 so we can use appendAssumeCapacity on the root node below.
88+
const estimated_node_count = (tokens.len + 2) / 2;
89+
try parser.nodes.ensureTotalCapacity(gpa, estimated_node_count);
90+
91+
switch (mode) {
92+
.zig => try parser.parseRoot(),
93+
.zon => try parser.parseZon(),
94+
}
95+
96+
// TODO experiment with compacting the MultiArrayList slices here
97+
return Ast{
98+
.source = source,
99+
.tokens = tokens.toOwnedSlice(),
100+
.nodes = parser.nodes.toOwnedSlice(),
101+
.extra_data = try parser.extra_data.toOwnedSlice(gpa),
102+
.errors = try parser.errors.toOwnedSlice(gpa),
103+
};
104+
}
105+
51106
/// `gpa` is used for allocating the resulting formatted source code, as well as
52107
/// for allocating extra stack memory if needed, because this function utilizes recursion.
53108
/// Note: that's not actually true yet, see https://github.com/ziglang/zig/issues/1006.
54109
/// Caller owns the returned slice of bytes, allocated with `gpa`.
55-
pub fn render(tree: Ast, gpa: mem.Allocator) RenderError![]u8 {
110+
pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 {
56111
var buffer = std.ArrayList(u8).init(gpa);
57112
defer buffer.deinit();
58113

@@ -3347,3 +3402,12 @@ pub const Node = struct {
33473402
rparen: TokenIndex,
33483403
};
33493404
};
3405+
3406+
const std = @import("../std.zig");
3407+
const assert = std.debug.assert;
3408+
const testing = std.testing;
3409+
const mem = std.mem;
3410+
const Token = std.zig.Token;
3411+
const Ast = @This();
3412+
const Allocator = std.mem.Allocator;
3413+
const Parse = @import("Parse.zig");

0 commit comments

Comments
 (0)