zig fmt: parse extra comma in asm expressions

master
Andrew Kelley 2018-05-26 16:37:55 -04:00
parent 85ca611af1
commit 0ab888c639
4 changed files with 120 additions and 29 deletions

View File

@ -2071,7 +2071,7 @@ pub const Node = struct {
const OutputList = SegmentedList(&AsmOutput, 2);
const InputList = SegmentedList(&AsmInput, 2);
const ClobberList = SegmentedList(&Node, 2);
const ClobberList = SegmentedList(TokenIndex, 2);
pub fn iterate(self: &Asm, index: usize) ?&Node {
var i = index;

View File

@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.AsmClobberItems => |items| {
stack.append(State{ .AsmClobberItems = items }) catch unreachable;
try stack.append(State{ .IfToken = Token.Id.Comma });
try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } });
while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {
try items.push(strlit);
if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)
break;
}
continue;
},

View File

@ -1,3 +1,44 @@
test "zig fmt: simple asm" {
try testTransform(
\\comptime {
\\ asm volatile (
\\ \\.globl aoeu;
\\ \\.type aoeu, @function;
\\ \\.set aoeu, derp;
\\ );
\\
\\ asm ("not real assembly"
\\ :[a] "x" (x),);
\\ asm ("not real assembly"
\\ :[a] "x" (->i32),:[a] "x" (1),);
\\ asm ("still not real assembly"
\\ :::"a","b",);
\\}
,
\\comptime {
\\ asm volatile (
\\ \\.globl aoeu;
\\ \\.type aoeu, @function;
\\ \\.set aoeu, derp;
\\ );
\\
\\ asm ("not real assembly"
\\ : [a] "x" (x)
\\ );
\\ asm ("not real assembly"
\\ : [a] "x" (-> i32)
\\ : [a] "x" (1)
\\ );
\\ asm ("still not real assembly"
\\ :
\\ :
\\ : "a", "b"
\\ );
\\}
\\
);
}
test "zig fmt: nested struct literal with one item" {
try testCanonical(
\\const a = foo{
@ -1295,7 +1336,8 @@ test "zig fmt: inline asm" {
\\ : [ret] "={rax}" (-> usize)
\\ : [number] "{rax}" (number),
\\ [arg1] "{rdi}" (arg1)
\\ : "rcx", "r11");
\\ : "rcx", "r11"
\\ );
\\}
\\
);

View File

@ -1203,19 +1203,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (
}
if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.None);
try renderToken(tree, stream, asm_node.rparen, indent, space);
return;
}
try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);
const indent_once = indent + indent_delta;
try stream.writeByteNTimes(' ', indent_once);
try stream.print(": ");
const colon1 = tree.nextToken(asm_node.template.lastToken());
const indent_extra = indent_once + 2;
{
const colon2 = if (asm_node.outputs.len == 0) blk: {
try renderToken(tree, stream, colon1, indent, Space.Newline); // :
try stream.writeByteNTimes(' ', indent_once);
break :blk tree.nextToken(colon1);
} else blk: {
try renderToken(tree, stream, colon1, indent, Space.Space); // :
var it = asm_node.outputs.iterator(0);
while (it.next()) |asm_output| {
while (true) {
const asm_output = ??it.next();
const node = &(asm_output.*).base;
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
if (it.peek()) |next_asm_output| {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
const next_node = &(next_asm_output.*).base;
const comma = tree.prevToken(next_asm_output.*.firstToken());
@ -1223,21 +1239,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderExtraNewline(tree, stream, next_node);
try stream.writeByteNTimes(' ', indent_extra);
} else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
try stream.writeByteNTimes(' ', indent);
try renderToken(tree, stream, asm_node.rparen, indent, space);
return;
} else {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
try stream.writeByteNTimes(' ', indent_once);
const comma_or_colon = tree.nextToken(node.lastToken());
break :blk switch (tree.tokens.at(comma_or_colon).id) {
Token.Id.Comma => tree.nextToken(comma_or_colon),
else => comma_or_colon,
};
}
}
}
};
try stream.write("\n");
try stream.writeByteNTimes(' ', indent_once);
try stream.write(": ");
const colon3 = if (asm_node.inputs.len == 0) blk: {
try renderToken(tree, stream, colon2, indent, Space.Newline); // :
try stream.writeByteNTimes(' ', indent_once);
break :blk tree.nextToken(colon2);
} else blk: {
try renderToken(tree, stream, colon2, indent, Space.Space); // :
{
var it = asm_node.inputs.iterator(0);
while (it.next()) |asm_input| {
while (true) {
const asm_input = ??it.next();
const node = &(asm_input.*).base;
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
if (it.peek()) |next_asm_input| {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
const next_node = &(next_asm_input.*).base;
const comma = tree.prevToken(next_asm_input.*.firstToken());
@ -1245,26 +1278,40 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderExtraNewline(tree, stream, next_node);
try stream.writeByteNTimes(' ', indent_extra);
} else if (asm_node.clobbers.len == 0) {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
try stream.writeByteNTimes(' ', indent);
try renderToken(tree, stream, asm_node.rparen, indent, space); // )
return;
} else {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
try stream.writeByteNTimes(' ', indent_once);
const comma_or_colon = tree.nextToken(node.lastToken());
break :blk switch (tree.tokens.at(comma_or_colon).id) {
Token.Id.Comma => tree.nextToken(comma_or_colon),
else => comma_or_colon,
};
}
}
}
};
try stream.write("\n");
try stream.writeByteNTimes(' ', indent_once);
try stream.write(": ");
try renderToken(tree, stream, colon3, indent, Space.Space); // :
{
var it = asm_node.clobbers.iterator(0);
while (it.next()) |node| {
try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None);
var it = asm_node.clobbers.iterator(0);
while (true) {
const clobber_token = ??it.next();
if (it.peek() != null) {
try stream.write(", ");
}
if (it.peek() == null) {
try renderToken(tree, stream, clobber_token.*, indent_once, Space.Newline);
try stream.writeByteNTimes(' ', indent);
try renderToken(tree, stream, asm_node.rparen, indent, space);
return;
} else {
try renderToken(tree, stream, clobber_token.*, indent_once, Space.None);
const comma = tree.nextToken(clobber_token.*);
try renderToken(tree, stream, comma, indent_once, Space.Space); // ,
}
}
try renderToken(tree, stream, asm_node.rparen, indent, space);
},
ast.Node.Id.AsmInput => {