authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-25 00:37:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-25 00:38:07-04:00
loge6afea99a9642a4fe12b65ef94fee0ee34d7a36b
tree9226f2fe7b4d29a5914fe440a349916e8b42523d
parentb74dda34b6a8b5f04d1865e2f23aab43229815f9

zig fmt: support aligned ptr with bit fields


4 files changed, 103 insertions(+), 24 deletions(-)

std/zig/ast.zig+17-5
...@@ -98,6 +98,7 @@ pub const Error = union(enum) {...@@ -98,6 +98,7 @@ pub const Error = union(enum) {
98 UnattachedDocComment: UnattachedDocComment,98 UnattachedDocComment: UnattachedDocComment,
99 ExpectedEqOrSemi: ExpectedEqOrSemi,99 ExpectedEqOrSemi: ExpectedEqOrSemi,
100 ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,100 ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,
101 ExpectedColonOrRParen: ExpectedColonOrRParen,
101 ExpectedLabelable: ExpectedLabelable,102 ExpectedLabelable: ExpectedLabelable,
102 ExpectedInlinable: ExpectedInlinable,103 ExpectedInlinable: ExpectedInlinable,
103 ExpectedAsmOutputReturnOrType: ExpectedAsmOutputReturnOrType,104 ExpectedAsmOutputReturnOrType: ExpectedAsmOutputReturnOrType,
...@@ -120,6 +121,7 @@ pub const Error = union(enum) {...@@ -120,6 +121,7 @@ pub const Error = union(enum) {
120 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),121 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
121 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),122 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
122 @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),123 @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
124 @TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
123 @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream),125 @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream),
124 @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream),126 @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream),
125 @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),127 @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
...@@ -144,6 +146,7 @@ pub const Error = union(enum) {...@@ -144,6 +146,7 @@ pub const Error = union(enum) {
144 @TagType(Error).UnattachedDocComment => |x| return x.token,146 @TagType(Error).UnattachedDocComment => |x| return x.token,
145 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,147 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,
146 @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token,148 @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token,
149 @TagType(Error).ExpectedColonOrRParen => |x| return x.token,
147 @TagType(Error).ExpectedLabelable => |x| return x.token,150 @TagType(Error).ExpectedLabelable => |x| return x.token,
148 @TagType(Error).ExpectedInlinable => |x| return x.token,151 @TagType(Error).ExpectedInlinable => |x| return x.token,
149 @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token,152 @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token,
...@@ -164,6 +167,7 @@ pub const Error = union(enum) {...@@ -164,6 +167,7 @@ pub const Error = union(enum) {
164 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");167 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
165 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");168 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
166 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");169 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
170 pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found {}");
167 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");171 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");
168 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");172 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");
169 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");173 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");
...@@ -1487,7 +1491,7 @@ pub const Node = struct {...@@ -1487,7 +1491,7 @@ pub const Node = struct {
1487 op: Op,1491 op: Op,
1488 rhs: &Node,1492 rhs: &Node,
14891493
1490 const Op = union(enum) {1494 pub const Op = union(enum) {
1491 AddrOf: AddrOfInfo,1495 AddrOf: AddrOfInfo,
1492 ArrayType: &Node,1496 ArrayType: &Node,
1493 Await,1497 Await,
...@@ -1504,12 +1508,20 @@ pub const Node = struct {...@@ -1504,12 +1508,20 @@ pub const Node = struct {
1504 UnwrapMaybe,1508 UnwrapMaybe,
1505 };1509 };
15061510
1507 const AddrOfInfo = struct {1511 pub const AddrOfInfo = struct {
1508 align_expr: ?&Node,1512 align_info: ?Align,
1509 bit_offset_start_token: ?TokenIndex,
1510 bit_offset_end_token: ?TokenIndex,
1511 const_token: ?TokenIndex,1513 const_token: ?TokenIndex,
1512 volatile_token: ?TokenIndex,1514 volatile_token: ?TokenIndex,
1515
1516 pub const Align = struct {
1517 node: &Node,
1518 bit_range: ?BitRange,
1519
1520 pub const BitRange = struct {
1521 start: &Node,
1522 end: &Node,
1523 };
1524 };
1513 };1525 };
15141526
1515 pub fn iterate(self: &PrefixOp, index: usize) ?&Node {1527 pub fn iterate(self: &PrefixOp, index: usize) ?&Node {
std/zig/parse.zig+39-9
...@@ -1450,9 +1450,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1450,9 +1450,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1450 State.SliceOrArrayType => |node| {1450 State.SliceOrArrayType => |node| {
1451 if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {1451 if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {
1452 node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{1452 node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{
1453 .align_expr = null,1453 .align_info = null,
1454 .bit_offset_start_token = null,
1455 .bit_offset_end_token = null,
1456 .const_token = null,1454 .const_token = null,
1457 .volatile_token = null,1455 .volatile_token = null,
1458 } };1456 } };
...@@ -1467,6 +1465,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1467,6 +1465,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1467 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } });1465 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } });
1468 continue;1466 continue;
1469 },1467 },
1468
1470 State.AddrOfModifiers => |addr_of_info| {1469 State.AddrOfModifiers => |addr_of_info| {
1471 const token = nextToken(&tok_it, &tree);1470 const token = nextToken(&tok_it, &tree);
1472 const token_index = token.index;1471 const token_index = token.index;
...@@ -1474,12 +1473,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1474,12 +1473,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1474 switch (token_ptr.id) {1473 switch (token_ptr.id) {
1475 Token.Id.Keyword_align => {1474 Token.Id.Keyword_align => {
1476 stack.append(state) catch unreachable;1475 stack.append(state) catch unreachable;
1477 if (addr_of_info.align_expr != null) {1476 if (addr_of_info.align_info != null) {
1478 ((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } };1477 ((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } };
1479 return tree;1478 return tree;
1480 }1479 }
1481 try stack.append(State{ .ExpectToken = Token.Id.RParen });1480 addr_of_info.align_info = ast.Node.PrefixOp.AddrOfInfo.Align {
1482 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &addr_of_info.align_expr } });1481 .node = undefined,
1482 .bit_range = null,
1483 };
1484 // TODO https://github.com/ziglang/zig/issues/1022
1485 const align_info = &??addr_of_info.align_info;
1486
1487 try stack.append(State{ .AlignBitRange = align_info });
1488 try stack.append(State{ .Expression = OptionalCtx{ .Required = &align_info.node } });
1483 try stack.append(State{ .ExpectToken = Token.Id.LParen });1489 try stack.append(State{ .ExpectToken = Token.Id.LParen });
1484 continue;1490 continue;
1485 },1491 },
...@@ -1508,6 +1514,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1508,6 +1514,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1508 }1514 }
1509 },1515 },
15101516
1517 State.AlignBitRange => |align_info| {
1518 const token = nextToken(&tok_it, &tree);
1519 switch (token.ptr.id) {
1520 Token.Id.Colon => {
1521 align_info.bit_range = ast.Node.PrefixOp.AddrOfInfo.Align.BitRange(undefined);
1522 const bit_range = &??align_info.bit_range;
1523
1524 try stack.append(State{ .ExpectToken = Token.Id.RParen });
1525 try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.end } });
1526 try stack.append(State{ .ExpectToken = Token.Id.Colon });
1527 try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.start } });
1528 continue;
1529 },
1530 Token.Id.RParen => continue,
1531 else => {
1532 (try tree.errors.addOne()).* = Error{
1533 .ExpectedColonOrRParen = Error.ExpectedColonOrRParen{
1534 .token = token.index,
1535 }
1536 };
1537 return tree;
1538 },
1539 }
1540 },
1541
1511 State.Payload => |opt_ctx| {1542 State.Payload => |opt_ctx| {
1512 const token = nextToken(&tok_it, &tree);1543 const token = nextToken(&tok_it, &tree);
1513 const token_index = token.index;1544 const token_index = token.index;
...@@ -2801,6 +2832,7 @@ const State = union(enum) {...@@ -2801,6 +2832,7 @@ const State = union(enum) {
2801 SliceOrArrayAccess: &ast.Node.SuffixOp,2832 SliceOrArrayAccess: &ast.Node.SuffixOp,
2802 SliceOrArrayType: &ast.Node.PrefixOp,2833 SliceOrArrayType: &ast.Node.PrefixOp,
2803 AddrOfModifiers: &ast.Node.PrefixOp.AddrOfInfo,2834 AddrOfModifiers: &ast.Node.PrefixOp.AddrOfInfo,
2835 AlignBitRange: &ast.Node.PrefixOp.AddrOfInfo.Align,
28042836
2805 Payload: OptionalCtx,2837 Payload: OptionalCtx,
2806 PointerPayload: OptionalCtx,2838 PointerPayload: OptionalCtx,
...@@ -3120,9 +3152,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {...@@ -3120,9 +3152,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
3120 Token.Id.Asterisk,3152 Token.Id.Asterisk,
3121 Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} },3153 Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} },
3122 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{3154 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{
3123 .align_expr = null,3155 .align_info = null,
3124 .bit_offset_start_token = null,
3125 .bit_offset_end_token = null,
3126 .const_token = null,3156 .const_token = null,
3127 .volatile_token = null,3157 .volatile_token = null,
3128 } },3158 } },
std/zig/parser_test.zig+9
...@@ -1,3 +1,12 @@...@@ -1,3 +1,12 @@
1test "zig fmt: float literal with exponent" {
2 try testCanonical(
3 \\test "bit field alignment" {
4 \\ assert(@typeOf(&blah.b) == &align(1:3:6) const u3);
5 \\}
6 \\
7 );
8}
9
1test "zig fmt: float literal with exponent" {10test "zig fmt: float literal with exponent" {
2 try testCanonical(11 try testCanonical(
3 \\test "aoeu" {12 \\test "aoeu" {
std/zig/render.zig+38-10
...@@ -253,17 +253,30 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -253,17 +253,30 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
253 switch (prefix_op_node.op) {253 switch (prefix_op_node.op) {
254 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {254 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
255 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &255 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &
256 if (addr_of_info.align_expr) |align_expr| {256 if (addr_of_info.align_info) |align_info| {
257 const align_token = tree.nextToken(prefix_op_node.op_token);257 const align_token = tree.nextToken(prefix_op_node.op_token);
258 try renderToken(tree, stream, align_token, indent, Space.None); // align258 try renderToken(tree, stream, align_token, indent, Space.None); // align
259259
260 const lparen_token = tree.prevToken(align_expr.firstToken());260 const lparen_token = tree.prevToken(align_info.node.firstToken());
261 try renderToken(tree, stream, lparen_token, indent, Space.None); // (261 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
262262
263 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);263 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
264264
265 const rparen_token = tree.nextToken(align_expr.lastToken());265 if (align_info.bit_range) |bit_range| {
266 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )266 const colon1 = tree.prevToken(bit_range.start.firstToken());
267 const colon2 = tree.prevToken(bit_range.end.firstToken());
268
269 try renderToken(tree, stream, colon1, indent, Space.None); // :
270 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
271 try renderToken(tree, stream, colon2, indent, Space.None); // :
272 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
273
274 const rparen_token = tree.nextToken(bit_range.end.lastToken());
275 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
276 } else {
277 const rparen_token = tree.nextToken(align_info.node.lastToken());
278 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
279 }
267 }280 }
268 if (addr_of_info.const_token) |const_token| {281 if (addr_of_info.const_token) |const_token| {
269 try renderToken(tree, stream, const_token, indent, Space.Space); // const282 try renderToken(tree, stream, const_token, indent, Space.Space); // const
...@@ -272,21 +285,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -272,21 +285,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
272 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile285 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
273 }286 }
274 },287 },
288
275 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {289 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
276 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [290 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
277 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]291 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]
278292
279 if (addr_of_info.align_expr) |align_expr| {293 if (addr_of_info.align_info) |align_info| {
280 const align_token = tree.nextToken(prefix_op_node.op_token);294 const align_token = tree.nextToken(prefix_op_node.op_token);
281 try renderToken(tree, stream, align_token, indent, Space.None); // align295 try renderToken(tree, stream, align_token, indent, Space.None); // align
282296
283 const lparen_token = tree.prevToken(align_expr.firstToken());297 const lparen_token = tree.prevToken(align_info.node.firstToken());
284 try renderToken(tree, stream, lparen_token, indent, Space.None); // (298 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
285299
286 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);300 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
287301
288 const rparen_token = tree.nextToken(align_expr.lastToken());302 if (align_info.bit_range) |bit_range| {
289 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )303 const colon1 = tree.prevToken(bit_range.start.firstToken());
304 const colon2 = tree.prevToken(bit_range.end.firstToken());
305
306 try renderToken(tree, stream, colon1, indent, Space.None); // :
307 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
308 try renderToken(tree, stream, colon2, indent, Space.None); // :
309 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
310
311 const rparen_token = tree.nextToken(bit_range.end.lastToken());
312 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
313 } else {
314 const rparen_token = tree.nextToken(align_info.node.lastToken());
315 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
316 }
290 }317 }
291 if (addr_of_info.const_token) |const_token| {318 if (addr_of_info.const_token) |const_token| {
292 try renderToken(tree, stream, const_token, indent, Space.Space);319 try renderToken(tree, stream, const_token, indent, Space.Space);
...@@ -295,6 +322,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -295,6 +322,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
295 try renderToken(tree, stream, volatile_token, indent, Space.Space);322 try renderToken(tree, stream, volatile_token, indent, Space.Space);
296 }323 }
297 },324 },
325
298 ast.Node.PrefixOp.Op.ArrayType => |array_index| {326 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
299 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [327 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
300 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);328 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);