Commit 725adf8332
Changed files (4)
lib
lib/std/zig/ast.zig
@@ -319,35 +319,54 @@ pub const Tree = struct {
}
},
- .GlobalVarDecl => unreachable,
- .LocalVarDecl => unreachable,
- .SimpleVarDecl => unreachable,
- .AlignedVarDecl => unreachable,
- .ArrayType => unreachable,
- .ArrayTypeSentinel => unreachable,
- .PtrTypeAligned => unreachable,
- .PtrTypeSentinel => unreachable,
- .PtrType => unreachable,
- .SliceType => unreachable,
- .StructInit => unreachable,
- .SwitchCaseMulti => unreachable,
- .WhileSimple => unreachable,
- .WhileCont => unreachable,
- .While => unreachable,
- .ForSimple => unreachable,
- .For => unreachable,
- .FnProtoSimple => unreachable,
- .FnProtoSimpleMulti => unreachable,
- .FnProtoOne => unreachable,
- .FnProto => unreachable,
- .ContainerDecl => unreachable,
- .ContainerDeclArg => unreachable,
- .TaggedUnion => unreachable,
- .TaggedUnionEnumTag => unreachable,
- .AsmOutput => unreachable,
- .AsmInput => unreachable,
- .ErrorValue => unreachable,
- .ErrorUnion => unreachable,
+ .GlobalVarDecl,
+ .LocalVarDecl,
+ .SimpleVarDecl,
+ .AlignedVarDecl,
+ => {
+ var i = main_tokens[n]; // mut token
+ while (i > 0) {
+ i -= 1;
+ switch (token_tags[i]) {
+ .Keyword_extern,
+ .Keyword_export,
+ .Keyword_comptime,
+ .Keyword_pub,
+ .Keyword_threadlocal,
+ .StringLiteral,
+ => continue,
+
+ else => return i + 1,
+ }
+ }
+ return i;
+ },
+
+ .ArrayType => unreachable, // TODO
+ .ArrayTypeSentinel => unreachable, // TODO
+ .PtrTypeAligned => unreachable, // TODO
+ .PtrTypeSentinel => unreachable, // TODO
+ .PtrType => unreachable, // TODO
+ .SliceType => unreachable, // TODO
+ .StructInit => unreachable, // TODO
+ .SwitchCaseMulti => unreachable, // TODO
+ .WhileSimple => unreachable, // TODO
+ .WhileCont => unreachable, // TODO
+ .While => unreachable, // TODO
+ .ForSimple => unreachable, // TODO
+ .For => unreachable, // TODO
+ .FnProtoSimple => unreachable, // TODO
+ .FnProtoSimpleMulti => unreachable, // TODO
+ .FnProtoOne => unreachable, // TODO
+ .FnProto => unreachable, // TODO
+ .ContainerDecl => unreachable, // TODO
+ .ContainerDeclArg => unreachable, // TODO
+ .TaggedUnion => unreachable, // TODO
+ .TaggedUnionEnumTag => unreachable, // TODO
+ .AsmOutput => unreachable, // TODO
+ .AsmInput => unreachable, // TODO
+ .ErrorValue => unreachable, // TODO
+ .ErrorUnion => unreachable, // TODO
};
}
@@ -445,7 +464,9 @@ pub const Tree = struct {
.Identifier,
=> return main_tokens[n] + end_offset,
- .Call => {
+ .Call,
+ .BuiltinCall,
+ => {
end_offset += 1; // for the `)`
const params = tree.extraData(datas[n].rhs, Node.SubRange);
if (params.end - params.start == 0) {
@@ -453,69 +474,81 @@ pub const Tree = struct {
}
n = tree.extra_data[params.end - 1]; // last parameter
},
- .CallOne => {
- end_offset += 1; // for the `)`
+ .CallOne,
+ .ArrayAccess,
+ => {
+ end_offset += 1; // for the rparen/rbracket
if (datas[n].rhs == 0) {
return main_tokens[n] + end_offset;
}
n = datas[n].rhs;
},
+ .BuiltinCallTwo => {
+ end_offset += 1; // for the rparen
+ if (datas[n].rhs == 0) {
+ if (datas[n].lhs == 0) {
+ return main_tokens[n] + end_offset;
+ } else {
+ n = datas[n].lhs;
+ }
+ } else {
+ n = datas[n].rhs;
+ }
+ },
+
.ContainerFieldInit => unreachable,
.ContainerFieldAlign => unreachable,
.ContainerField => unreachable,
- .ArrayInitDotTwo => unreachable,
- .ArrayInitDot => unreachable,
- .StructInitDotTwo => unreachable,
- .StructInitDot => unreachable,
- .Switch => unreachable,
- .If => unreachable,
- .Continue => unreachable,
- .EnumLiteral => unreachable,
- .BuiltinCallTwo => unreachable,
- .BuiltinCall => unreachable,
- .ErrorSetDecl => unreachable,
- .Block => unreachable,
- .AsmSimple => unreachable,
- .Asm => unreachable,
- .SliceOpen => unreachable,
- .Slice => unreachable,
- .Deref => unreachable,
- .ArrayAccess => unreachable,
- .ArrayInitOne => unreachable,
- .ArrayInit => unreachable,
- .StructInitOne => unreachable,
- .SwitchCaseOne => unreachable,
- .SwitchRange => unreachable,
- .FnDecl => unreachable,
- .GlobalVarDecl => unreachable,
- .LocalVarDecl => unreachable,
- .SimpleVarDecl => unreachable,
- .AlignedVarDecl => unreachable,
- .ArrayType => unreachable,
- .ArrayTypeSentinel => unreachable,
- .PtrTypeAligned => unreachable,
- .PtrTypeSentinel => unreachable,
- .PtrType => unreachable,
- .SliceType => unreachable,
- .StructInit => unreachable,
- .SwitchCaseMulti => unreachable,
- .WhileCont => unreachable,
- .While => unreachable,
- .ForSimple => unreachable,
- .For => unreachable,
- .FnProtoSimple => unreachable,
- .FnProtoSimpleMulti => unreachable,
- .FnProtoOne => unreachable,
- .FnProto => unreachable,
- .ContainerDecl => unreachable,
- .ContainerDeclArg => unreachable,
- .TaggedUnion => unreachable,
- .TaggedUnionEnumTag => unreachable,
- .AsmOutput => unreachable,
- .AsmInput => unreachable,
- .ErrorValue => unreachable,
+ .ArrayInitDotTwo => unreachable, // TODO
+ .ArrayInitDot => unreachable, // TODO
+ .StructInitDotTwo => unreachable, // TODO
+ .StructInitDot => unreachable, // TODO
+ .Switch => unreachable, // TODO
+ .If => unreachable, // TODO
+ .Continue => unreachable, // TODO
+ .EnumLiteral => unreachable, // TODO
+ .ErrorSetDecl => unreachable, // TODO
+ .Block => unreachable, // TODO
+ .AsmSimple => unreachable, // TODO
+ .Asm => unreachable, // TODO
+ .SliceOpen => unreachable, // TODO
+ .Slice => unreachable, // TODO
+ .Deref => unreachable, // TODO
+ .ArrayInitOne => unreachable, // TODO
+ .ArrayInit => unreachable, // TODO
+ .StructInitOne => unreachable, // TODO
+ .SwitchCaseOne => unreachable, // TODO
+ .SwitchRange => unreachable, // TODO
+ .FnDecl => unreachable, // TODO
+ .GlobalVarDecl => unreachable, // TODO
+ .LocalVarDecl => unreachable, // TODO
+ .SimpleVarDecl => unreachable, // TODO
+ .AlignedVarDecl => unreachable, // TODO
+ .ArrayType => unreachable, // TODO
+ .ArrayTypeSentinel => unreachable, // TODO
+ .PtrTypeAligned => unreachable, // TODO
+ .PtrTypeSentinel => unreachable, // TODO
+ .PtrType => unreachable, // TODO
+ .SliceType => unreachable, // TODO
+ .StructInit => unreachable, // TODO
+ .SwitchCaseMulti => unreachable, // TODO
+ .WhileCont => unreachable, // TODO
+ .While => unreachable, // TODO
+ .ForSimple => unreachable, // TODO
+ .For => unreachable, // TODO
+ .FnProtoSimple => unreachable, // TODO
+ .FnProtoSimpleMulti => unreachable, // TODO
+ .FnProtoOne => unreachable, // TODO
+ .FnProto => unreachable, // TODO
+ .ContainerDecl => unreachable, // TODO
+ .ContainerDeclArg => unreachable, // TODO
+ .TaggedUnion => unreachable, // TODO
+ .TaggedUnionEnumTag => unreachable, // TODO
+ .AsmOutput => unreachable, // TODO
+ .AsmInput => unreachable, // TODO
+ .ErrorValue => unreachable, // TODO
};
}
lib/std/zig/parse.zig
@@ -3483,9 +3483,8 @@ const Parser = struct {
/// ExprList <- (Expr COMMA)* Expr?
/// TODO detect when we can emit BuiltinCallTwo instead of BuiltinCall.
fn parseBuiltinCall(p: *Parser) !Node.Index {
- const builtin_token = p.eatToken(.Builtin) orelse return null_node;
-
- const lparen = (try p.expectTokenRecoverable(.LParen)) orelse {
+ const builtin_token = p.assertToken(.Builtin);
+ _ = (try p.expectTokenRecoverable(.LParen)) orelse {
try p.warn(.{
.ExpectedParamList = .{ .token = p.tok_i },
});
@@ -3499,8 +3498,104 @@ const Parser = struct {
},
});
};
- const params = try ListParseFn(parseExpr)(p);
- _ = try p.expectToken(.RParen);
+ if (p.eatToken(.RParen)) |_| {
+ return p.addNode(.{
+ .tag = .BuiltinCallTwo,
+ .main_token = builtin_token,
+ .data = .{
+ .lhs = 0,
+ .rhs = 0,
+ },
+ });
+ }
+ const param_one = try p.expectExpr();
+ switch (p.token_tags[p.nextToken()]) {
+ .Comma => {
+ if (p.eatToken(.RParen)) |_| {
+ return p.addNode(.{
+ .tag = .BuiltinCallTwo,
+ .main_token = builtin_token,
+ .data = .{
+ .lhs = param_one,
+ .rhs = 0,
+ },
+ });
+ }
+ },
+ .RParen => return p.addNode(.{
+ .tag = .BuiltinCallTwo,
+ .main_token = builtin_token,
+ .data = .{
+ .lhs = param_one,
+ .rhs = 0,
+ },
+ }),
+ else => {
+ // This is likely just a missing comma;
+ // give an error but continue parsing this list.
+ p.tok_i -= 1;
+ try p.warn(.{
+ .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
+ });
+ },
+ }
+ const param_two = try p.expectExpr();
+ switch (p.token_tags[p.nextToken()]) {
+ .Comma => {
+ if (p.eatToken(.RParen)) |_| {
+ return p.addNode(.{
+ .tag = .BuiltinCallTwo,
+ .main_token = builtin_token,
+ .data = .{
+ .lhs = param_one,
+ .rhs = param_two,
+ },
+ });
+ }
+ },
+ .RParen => return p.addNode(.{
+ .tag = .BuiltinCallTwo,
+ .main_token = builtin_token,
+ .data = .{
+ .lhs = param_one,
+ .rhs = param_two,
+ },
+ }),
+ else => {
+ // This is likely just a missing comma;
+ // give an error but continue parsing this list.
+ p.tok_i -= 1;
+ try p.warn(.{
+ .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
+ });
+ },
+ }
+
+ var list = std.ArrayList(Node.Index).init(p.gpa);
+ defer list.deinit();
+
+ try list.appendSlice(&[_]Node.Index{ param_one, param_two });
+
+ while (true) {
+ const param = try p.expectExpr();
+ try list.append(param);
+ switch (p.token_tags[p.nextToken()]) {
+ .Comma => {
+ if (p.eatToken(.RParen)) |_| break;
+ continue;
+ },
+ .RParen => break,
+ else => {
+ // This is likely just a missing comma;
+ // give an error but continue parsing this list.
+ p.tok_i -= 1;
+ try p.warn(.{
+ .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
+ });
+ },
+ }
+ }
+ const params = try p.listToSpan(list.items);
return p.addNode(.{
.tag = .BuiltinCall,
.main_token = builtin_token,
lib/std/zig/parser_test.zig
@@ -21,21 +21,21 @@ test "zig fmt: two spaced line comments before decl" {
);
}
-//test "zig fmt: respect line breaks after var declarations" {
-// try testCanonical(
-// \\const crc =
-// \\ lookup_tables[0][p[7]] ^
-// \\ lookup_tables[1][p[6]] ^
-// \\ lookup_tables[2][p[5]] ^
-// \\ lookup_tables[3][p[4]] ^
-// \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
-// \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
-// \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
-// \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
-// \\
-// );
-//}
-//
+test "zig fmt: respect line breaks after var declarations" {
+ try testCanonical(
+ \\const crc =
+ \\ lookup_tables[0][p[7]] ^
+ \\ lookup_tables[1][p[6]] ^
+ \\ lookup_tables[2][p[5]] ^
+ \\ lookup_tables[3][p[4]] ^
+ \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
+ \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
+ \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
+ \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
+ \\
+ );
+}
+
//test "zig fmt: multiline string mixed with comments" {
// try testCanonical(
// \\const s1 =
lib/std/zig/render.zig
@@ -308,7 +308,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
const field_access = datas[node];
try renderExpression(ais, tree, field_access.lhs, .None);
try renderToken(ais, tree, main_tokens[node], .None);
- return renderToken(ais, tree, field_access.rhs, .None);
+ return renderToken(ais, tree, field_access.rhs, space);
},
.ErrorUnion,
@@ -362,18 +362,15 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
=> {
const infix = datas[node];
try renderExpression(ais, tree, infix.lhs, .Space);
-
const op_token = main_tokens[node];
- const after_op_space: Space = if (tree.tokensOnSameLine(op_token, op_token + 1))
- .Space
- else
- .Newline;
- {
+ if (tree.tokensOnSameLine(op_token, op_token + 1)) {
+ try renderToken(ais, tree, op_token, .Space);
+ } else {
ais.pushIndent();
- try renderToken(ais, tree, op_token, after_op_space);
+ try renderToken(ais, tree, op_token, .Newline);
ais.popIndent();
+ ais.pushIndentOneShot();
}
- ais.pushIndentOneShot();
return renderExpression(ais, tree, infix.rhs, space);
},
@@ -955,28 +952,15 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
return renderToken(ais, tree, after_last_param_tok, space); // )
},
- .ArrayAccess => unreachable, // TODO
- //.ArrayAccess => {
- // const suffix_op = base.castTag(.ArrayAccess).?;
-
- // const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
- // const rbracket = tree.nextToken(suffix_op.index_expr.lastToken());
-
- // try renderExpression(ais, tree, suffix_op.lhs, Space.None);
- // try renderToken(ais, tree, lbracket, Space.None); // [
-
- // const starts_with_comment = tree.token_tags[lbracket + 1] == .LineComment;
- // const ends_with_comment = tree.token_tags[rbracket - 1] == .LineComment;
- // {
- // const new_space = if (ends_with_comment) Space.Newline else Space.None;
-
- // ais.pushIndent();
- // defer ais.popIndent();
- // try renderExpression(ais, tree, suffix_op.index_expr, new_space);
- // }
- // if (starts_with_comment) try ais.maybeInsertNewline();
- // return renderToken(ais, tree, rbracket, space); // ]
- //},
+ .ArrayAccess => {
+ const suffix = datas[node];
+ const lbracket = tree.firstToken(suffix.rhs) - 1;
+ const rbracket = tree.lastToken(suffix.rhs) + 1;
+ try renderExpression(ais, tree, suffix.lhs, .None);
+ try renderToken(ais, tree, lbracket, .None); // [
+ try renderExpression(ais, tree, suffix.rhs, .None);
+ return renderToken(ais, tree, rbracket, space); // ]
+ },
.Slice => unreachable, // TODO
.SliceOpen => unreachable, // TODO
@@ -1278,68 +1262,22 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
// }
//},
- .BuiltinCall => unreachable, // TODO
- .BuiltinCallTwo => unreachable, // TODO
- //.BuiltinCall => {
- // const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
-
- // // TODO remove after 0.7.0 release
- // if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
- // return ais.writer().writeAll("opaque {}");
-
- // // TODO remove after 0.7.0 release
- // {
- // const params = builtin_call.paramsConst();
- // if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
- // params.len == 1)
- // {
- // if (params[0].castTag(.EnumLiteral)) |enum_literal|
- // if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
- // return ais.writer().writeAll("opaque {}");
- // }
- // }
-
- // try renderToken(ais, tree, builtin_call.builtin_token, Space.None); // @name
-
- // const src_params_trailing_comma = blk: {
- // if (builtin_call.params_len == 0) break :blk false;
- // const last_node = builtin_call.params()[builtin_call.params_len - 1];
- // const maybe_comma = tree.nextToken(last_node.lastToken());
- // break :blk tree.token_tags[maybe_comma] == .Comma;
- // };
-
- // const lparen = tree.nextToken(builtin_call.builtin_token);
-
- // if (!src_params_trailing_comma) {
- // try renderToken(ais, tree, lparen, Space.None); // (
-
- // // render all on one line, no trailing comma
- // const params = builtin_call.params();
- // for (params) |param_node, i| {
- // const maybe_comment = param_node.firstToken() - 1;
- // if (param_node.*.tag == .MultilineStringLiteral or tree.token_tags[maybe_comment] == .LineComment) {
- // ais.pushIndentOneShot();
- // }
- // try renderExpression(ais, tree, param_node, Space.None);
-
- // if (i + 1 < params.len) {
- // const comma_token = tree.nextToken(param_node.lastToken());
- // try renderToken(ais, tree, comma_token, Space.Space); // ,
- // }
- // }
- // } else {
- // // one param per line
- // ais.pushIndent();
- // defer ais.popIndent();
- // try renderToken(ais, tree, lparen, Space.Newline); // (
-
- // for (builtin_call.params()) |param_node| {
- // try renderExpression(ais, tree, param_node, Space.Comma);
- // }
- // }
-
- // return renderToken(ais, tree, builtin_call.rparen_token, space); // )
- //},
+ .BuiltinCallTwo => {
+ if (datas[node].lhs == 0) {
+ const params = [_]ast.Node.Index{};
+ return renderBuiltinCall(ais, tree, main_tokens[node], ¶ms, space);
+ } else if (datas[node].rhs == 0) {
+ const params = [_]ast.Node.Index{datas[node].lhs};
+ return renderBuiltinCall(ais, tree, main_tokens[node], ¶ms, space);
+ } else {
+ const params = [_]ast.Node.Index{ datas[node].lhs, datas[node].rhs };
+ return renderBuiltinCall(ais, tree, main_tokens[node], ¶ms, space);
+ }
+ },
+ .BuiltinCall => {
+ const params = tree.extra_data[datas[node].lhs..datas[node].rhs];
+ return renderBuiltinCall(ais, tree, main_tokens[node], params, space);
+ },
.FnProtoSimple => unreachable, // TODO
.FnProtoSimpleMulti => unreachable, // TODO
@@ -2221,6 +2159,52 @@ fn renderParamDecl(
}
}
+fn renderBuiltinCall(
+ ais: *Ais,
+ tree: ast.Tree,
+ builtin_token: ast.TokenIndex,
+ params: []const ast.Node.Index,
+ space: Space,
+) Error!void {
+ const token_tags = tree.tokens.items(.tag);
+
+ try renderToken(ais, tree, builtin_token, .None); // @name
+
+ if (params.len == 0) {
+ try renderToken(ais, tree, builtin_token + 1, .None); // (
+ return renderToken(ais, tree, builtin_token + 2, space); // )
+ }
+
+ const last_param = params[params.len - 1];
+ const after_last_param_token = tree.lastToken(last_param) + 1;
+
+ if (token_tags[after_last_param_token] != .Comma) {
+ // Render all on one line, no trailing comma.
+ try renderToken(ais, tree, builtin_token + 1, .None); // (
+
+ for (params) |param_node, i| {
+ try renderExpression(ais, tree, param_node, .None);
+
+ if (i + 1 < params.len) {
+ const comma_token = tree.lastToken(param_node) + 1;
+ try renderToken(ais, tree, comma_token, .Space); // ,
+ }
+ }
+ return renderToken(ais, tree, after_last_param_token, space); // )
+ } else {
+ // Render one param per line.
+ ais.pushIndent();
+ try renderToken(ais, tree, builtin_token + 1, Space.Newline); // (
+
+ for (params) |param_node| {
+ try renderExpression(ais, tree, param_node, .Comma);
+ }
+ ais.popIndent();
+
+ return renderToken(ais, tree, after_last_param_token + 1, space); // )
+ }
+}
+
/// Render an expression, and the comma that follows it, if it is present in the source.
fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
const token_tags = tree.tokens.items(.tag);