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 {
48134813 const br = blk_last.castTag(.break_val).?;
48144814 break :blk br.data.val;
48154815 } 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|
48174818 some.data.lhs
4819 else if (typeof_arg.castTag(.std_mem_zeroes)) |some|
4820 some.data
48184821 else
48194822 try Tag.typeof.create(c.arena, typeof_arg);
48204823
......@@ -4932,6 +4935,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
49324935 }
49334936 },
49344937 .FloatLiteral => |suffix| {
4938 if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1];
49354939 const dot_index = mem.indexOfScalar(u8, lit_bytes, '.').?;
49364940 if (dot_index == 0) {
49374941 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
......@@ -4943,15 +4947,16 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
49434947 lit_bytes[dot_index + 1 ..],
49444948 });
49454949 }
4946 if (suffix == .none) {
4950
4951 if (suffix == .none)
49474952 return transCreateNodeNumber(c, lit_bytes, .float);
4948 }
4953
49494954 const type_node = try Tag.type.create(c.arena, switch (suffix) {
49504955 .f => "f32",
49514956 .l => "c_longdouble",
49524957 else => unreachable,
49534958 });
4954 const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1], .float);
4959 const rhs = try transCreateNodeNumber(c, lit_bytes, .float);
49554960 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
49564961 },
49574962 else => unreachable,
......@@ -5540,6 +5545,42 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
55405545 }
55415546 },
55425547 .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
55435584 var init_vals = std.ArrayList(Node).init(c.gpa);
55445585 defer init_vals.deinit();
55455586
src/translate_c/ast.zig+52-9
......@@ -71,6 +71,7 @@ pub const Node = extern union {
7171 array_init,
7272 tuple,
7373 container_init,
74 container_init_dot,
7475 std_meta_cast,
7576 /// _ = operand;
7677 discard,
......@@ -332,6 +333,7 @@ pub const Node = extern union {
332333 .ptr_cast,
333334 .div_exact,
334335 .byte_offset_of,
336 .std_meta_cast,
335337 => Payload.BinOp,
336338
337339 .integer_literal,
......@@ -354,7 +356,7 @@ pub const Node = extern union {
354356 .@"struct", .@"union" => Payload.Record,
355357 .tuple => Payload.TupleInit,
356358 .container_init => Payload.ContainerInit,
357 .std_meta_cast => Payload.Infix,
359 .container_init_dot => Payload.ContainerInitDot,
358360 .std_meta_promoteIntLiteral => Payload.PromoteIntLiteral,
359361 .block => Payload.Block,
360362 .c_pointer, .single_pointer => Payload.Pointer,
......@@ -448,14 +450,6 @@ pub const Node = extern union {
448450pub const Payload = struct {
449451 tag: Node.Tag,
450452
451 pub const Infix = struct {
452 base: Payload,
453 data: struct {
454 lhs: Node,
455 rhs: Node,
456 },
457 };
458
459453 pub const Value = struct {
460454 base: Payload,
461455 data: []const u8,
......@@ -600,6 +594,16 @@ pub const Payload = struct {
600594 };
601595 };
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
603607 pub const Block = struct {
604608 base: Payload,
605609 data: struct {
......@@ -1893,6 +1897,44 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
18931897 });
18941898 }
18951899 },
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 },
18961938 .container_init => {
18971939 const payload = node.castTag(.container_init).?.data;
18981940 const lhs = try renderNode(c, payload.lhs);
......@@ -2257,6 +2299,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
22572299 .array_init,
22582300 .tuple,
22592301 .container_init,
2302 .container_init_dot,
22602303 .block,
22612304 => return c.addNode(.{
22622305 .tag = .grouped_expression,
test/translate_c.zig+15
......@@ -336,6 +336,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
336336 \\ int i1;
337337 \\} boom_t;
338338 \\#define FOO ((boom_t){1})
339 \\typedef struct { float x; } MyCStruct;
340 \\#define A(_x) (MyCStruct) { .x = (_x) }
341 \\#define B A(0.f)
339342 , &[_][]const u8{
340343 \\pub const struct_Color = extern struct {
341344 \\ r: u8,
......@@ -357,6 +360,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
357360 \\pub const boom_t = struct_boom_t;
358361 ,
359362 \\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));
360375 });
361376
362377 cases.add("complex switch",