authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-05-31 21:06:12+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-01 23:40:43-04:00
logc6a0a4e7282d746ebf2b54df16161c5993ea5aa8
tree70fae1d044589b07a8835e000e2c7c4e77726102
parent99b6305aa89c6363b1220a780485803a66880cce

translate-c: support designated initializers in macros


3 files changed, 112 insertions(+), 13 deletions(-)

src/translate_c.zig+45-4
...@@ -4813,8 +4813,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4813,8 +4813,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
4813 const br = blk_last.castTag(.break_val).?;4813 const br = blk_last.castTag(.break_val).?;
4814 break :blk br.data.val;4814 break :blk br.data.val;
4815 } else expr;4815 } else expr;
4816 const return_type = if (typeof_arg.castTag(.std_meta_cast)) |some|4816
4817 const return_type = if (typeof_arg.castTag(.std_meta_cast) orelse typeof_arg.castTag(.std_mem_zeroinit)) |some|
4817 some.data.lhs4818 some.data.lhs
4819 else if (typeof_arg.castTag(.std_mem_zeroes)) |some|
4820 some.data
4818 else4821 else
4819 try Tag.typeof.create(c.arena, typeof_arg);4822 try Tag.typeof.create(c.arena, typeof_arg);
48204823
...@@ -4932,6 +4935,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4932,6 +4935,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
4932 }4935 }
4933 },4936 },
4934 .FloatLiteral => |suffix| {4937 .FloatLiteral => |suffix| {
4938 if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1];
4935 const dot_index = mem.indexOfScalar(u8, lit_bytes, '.').?;4939 const dot_index = mem.indexOfScalar(u8, lit_bytes, '.').?;
4936 if (dot_index == 0) {4940 if (dot_index == 0) {
4937 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});4941 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
...@@ -4943,15 +4947,16 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4943,15 +4947,16 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
4943 lit_bytes[dot_index + 1 ..],4947 lit_bytes[dot_index + 1 ..],
4944 });4948 });
4945 }4949 }
4946 if (suffix == .none) {4950
4951 if (suffix == .none)
4947 return transCreateNodeNumber(c, lit_bytes, .float);4952 return transCreateNodeNumber(c, lit_bytes, .float);
4948 }4953
4949 const type_node = try Tag.type.create(c.arena, switch (suffix) {4954 const type_node = try Tag.type.create(c.arena, switch (suffix) {
4950 .f => "f32",4955 .f => "f32",
4951 .l => "c_longdouble",4956 .l => "c_longdouble",
4952 else => unreachable,4957 else => unreachable,
4953 });4958 });
4954 const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1], .float);4959 const rhs = try transCreateNodeNumber(c, lit_bytes, .float);
4955 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });4960 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
4956 },4961 },
4957 else => unreachable,4962 else => unreachable,
...@@ -5540,6 +5545,42 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -5540,6 +5545,42 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5540 }5545 }
5541 },5546 },
5542 .LBrace => {5547 .LBrace => {
5548 // Check for designated field initializers
5549 if (m.peek().? == .Period) {
5550 var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa);
5551 defer init_vals.deinit();
5552
5553 while (true) {
5554 if (m.next().? != .Period) {
5555 try m.fail(c, "unable to translate C expr: expected '.'", .{});
5556 return error.ParseError;
5557 }
5558 if (m.next().? != .Identifier) {
5559 try m.fail(c, "unable to translate C expr: expected identifier", .{});
5560 return error.ParseError;
5561 }
5562 const name = m.slice();
5563 if (m.next().? != .Equal) {
5564 try m.fail(c, "unable to translate C expr: expected '='", .{});
5565 return error.ParseError;
5566 }
5567
5568 const val = try parseCCondExpr(c, m, scope);
5569 try init_vals.append(.{ .name = name, .value = val });
5570 switch (m.next().?) {
5571 .Comma => {},
5572 .RBrace => break,
5573 else => {
5574 try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});
5575 return error.ParseError;
5576 },
5577 }
5578 }
5579 const tuple_node = try Tag.container_init_dot.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInitDot.Initializer, init_vals.items));
5580 node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
5581 continue;
5582 }
5583
5543 var init_vals = std.ArrayList(Node).init(c.gpa);5584 var init_vals = std.ArrayList(Node).init(c.gpa);
5544 defer init_vals.deinit();5585 defer init_vals.deinit();
55455586
src/translate_c/ast.zig+52-9
...@@ -71,6 +71,7 @@ pub const Node = extern union {...@@ -71,6 +71,7 @@ pub const Node = extern union {
71 array_init,71 array_init,
72 tuple,72 tuple,
73 container_init,73 container_init,
74 container_init_dot,
74 std_meta_cast,75 std_meta_cast,
75 /// _ = operand;76 /// _ = operand;
76 discard,77 discard,
...@@ -332,6 +333,7 @@ pub const Node = extern union {...@@ -332,6 +333,7 @@ pub const Node = extern union {
332 .ptr_cast,333 .ptr_cast,
333 .div_exact,334 .div_exact,
334 .byte_offset_of,335 .byte_offset_of,
336 .std_meta_cast,
335 => Payload.BinOp,337 => Payload.BinOp,
336338
337 .integer_literal,339 .integer_literal,
...@@ -354,7 +356,7 @@ pub const Node = extern union {...@@ -354,7 +356,7 @@ pub const Node = extern union {
354 .@"struct", .@"union" => Payload.Record,356 .@"struct", .@"union" => Payload.Record,
355 .tuple => Payload.TupleInit,357 .tuple => Payload.TupleInit,
356 .container_init => Payload.ContainerInit,358 .container_init => Payload.ContainerInit,
357 .std_meta_cast => Payload.Infix,359 .container_init_dot => Payload.ContainerInitDot,
358 .std_meta_promoteIntLiteral => Payload.PromoteIntLiteral,360 .std_meta_promoteIntLiteral => Payload.PromoteIntLiteral,
359 .block => Payload.Block,361 .block => Payload.Block,
360 .c_pointer, .single_pointer => Payload.Pointer,362 .c_pointer, .single_pointer => Payload.Pointer,
...@@ -448,14 +450,6 @@ pub const Node = extern union {...@@ -448,14 +450,6 @@ pub const Node = extern union {
448pub const Payload = struct {450pub const Payload = struct {
449 tag: Node.Tag,451 tag: Node.Tag,
450452
451 pub const Infix = struct {
452 base: Payload,
453 data: struct {
454 lhs: Node,
455 rhs: Node,
456 },
457 };
458
459 pub const Value = struct {453 pub const Value = struct {
460 base: Payload,454 base: Payload,
461 data: []const u8,455 data: []const u8,
...@@ -600,6 +594,16 @@ pub const Payload = struct {...@@ -600,6 +594,16 @@ pub const Payload = struct {
600 };594 };
601 };595 };
602596
597 pub const ContainerInitDot = struct {
598 base: Payload,
599 data: []Initializer,
600
601 pub const Initializer = struct {
602 name: []const u8,
603 value: Node,
604 };
605 };
606
603 pub const Block = struct {607 pub const Block = struct {
604 base: Payload,608 base: Payload,
605 data: struct {609 data: struct {
...@@ -1893,6 +1897,44 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1893,6 +1897,44 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1893 });1897 });
1894 }1898 }
1895 },1899 },
1900 .container_init_dot => {
1901 const payload = node.castTag(.container_init_dot).?.data;
1902 _ = try c.addToken(.period, ".");
1903 const l_brace = try c.addToken(.l_brace, "{");
1904 var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.len, 2));
1905 defer c.gpa.free(inits);
1906 inits[0] = 0;
1907 inits[1] = 0;
1908 for (payload) |init, i| {
1909 _ = try c.addToken(.period, ".");
1910 _ = try c.addIdentifier(init.name);
1911 _ = try c.addToken(.equal, "=");
1912 inits[i] = try renderNode(c, init.value);
1913 _ = try c.addToken(.comma, ",");
1914 }
1915 _ = try c.addToken(.r_brace, "}");
1916
1917 if (payload.len < 3) {
1918 return c.addNode(.{
1919 .tag = .struct_init_dot_two_comma,
1920 .main_token = l_brace,
1921 .data = .{
1922 .lhs = inits[0],
1923 .rhs = inits[1],
1924 },
1925 });
1926 } else {
1927 const span = try c.listToSpan(inits);
1928 return c.addNode(.{
1929 .tag = .struct_init_dot_comma,
1930 .main_token = l_brace,
1931 .data = .{
1932 .lhs = span.start,
1933 .rhs = span.end,
1934 },
1935 });
1936 }
1937 },
1896 .container_init => {1938 .container_init => {
1897 const payload = node.castTag(.container_init).?.data;1939 const payload = node.castTag(.container_init).?.data;
1898 const lhs = try renderNode(c, payload.lhs);1940 const lhs = try renderNode(c, payload.lhs);
...@@ -2257,6 +2299,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -2257,6 +2299,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
2257 .array_init,2299 .array_init,
2258 .tuple,2300 .tuple,
2259 .container_init,2301 .container_init,
2302 .container_init_dot,
2260 .block,2303 .block,
2261 => return c.addNode(.{2304 => return c.addNode(.{
2262 .tag = .grouped_expression,2305 .tag = .grouped_expression,
test/translate_c.zig+15
...@@ -336,6 +336,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -336,6 +336,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
336 \\ int i1;336 \\ int i1;
337 \\} boom_t;337 \\} boom_t;
338 \\#define FOO ((boom_t){1})338 \\#define FOO ((boom_t){1})
339 \\typedef struct { float x; } MyCStruct;
340 \\#define A(_x) (MyCStruct) { .x = (_x) }
341 \\#define B A(0.f)
339 , &[_][]const u8{342 , &[_][]const u8{
340 \\pub const struct_Color = extern struct {343 \\pub const struct_Color = extern struct {
341 \\ r: u8,344 \\ r: u8,
...@@ -357,6 +360,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -357,6 +360,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
357 \\pub const boom_t = struct_boom_t;360 \\pub const boom_t = struct_boom_t;
358 ,361 ,
359 \\pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)});362 \\pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)});
363 ,
364 \\pub const MyCStruct = extern struct {
365 \\ x: f32,
366 \\};
367 ,
368 \\pub inline fn A(_x: anytype) MyCStruct {
369 \\ return @import("std").mem.zeroInit(MyCStruct, .{
370 \\ .x = _x,
371 \\ });
372 \\}
373 ,
374 \\pub const B = A(@as(f32, 0.0));
360 });375 });
361376
362 cases.add("complex switch",377 cases.add("complex switch",