Commit c6a0a4e728
Changed files (3)
src
translate_c
test
src/translate_c/ast.zig
@@ -71,6 +71,7 @@ pub const Node = extern union {
array_init,
tuple,
container_init,
+ container_init_dot,
std_meta_cast,
/// _ = operand;
discard,
@@ -332,6 +333,7 @@ pub const Node = extern union {
.ptr_cast,
.div_exact,
.byte_offset_of,
+ .std_meta_cast,
=> Payload.BinOp,
.integer_literal,
@@ -354,7 +356,7 @@ pub const Node = extern union {
.@"struct", .@"union" => Payload.Record,
.tuple => Payload.TupleInit,
.container_init => Payload.ContainerInit,
- .std_meta_cast => Payload.Infix,
+ .container_init_dot => Payload.ContainerInitDot,
.std_meta_promoteIntLiteral => Payload.PromoteIntLiteral,
.block => Payload.Block,
.c_pointer, .single_pointer => Payload.Pointer,
@@ -448,14 +450,6 @@ pub const Node = extern union {
pub const Payload = struct {
tag: Node.Tag,
- pub const Infix = struct {
- base: Payload,
- data: struct {
- lhs: Node,
- rhs: Node,
- },
- };
-
pub const Value = struct {
base: Payload,
data: []const u8,
@@ -600,6 +594,16 @@ pub const Payload = struct {
};
};
+ pub const ContainerInitDot = struct {
+ base: Payload,
+ data: []Initializer,
+
+ pub const Initializer = struct {
+ name: []const u8,
+ value: Node,
+ };
+ };
+
pub const Block = struct {
base: Payload,
data: struct {
@@ -1893,6 +1897,44 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
});
}
},
+ .container_init_dot => {
+ const payload = node.castTag(.container_init_dot).?.data;
+ _ = try c.addToken(.period, ".");
+ const l_brace = try c.addToken(.l_brace, "{");
+ var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.len, 2));
+ defer c.gpa.free(inits);
+ inits[0] = 0;
+ inits[1] = 0;
+ for (payload) |init, i| {
+ _ = try c.addToken(.period, ".");
+ _ = try c.addIdentifier(init.name);
+ _ = try c.addToken(.equal, "=");
+ inits[i] = try renderNode(c, init.value);
+ _ = try c.addToken(.comma, ",");
+ }
+ _ = try c.addToken(.r_brace, "}");
+
+ if (payload.len < 3) {
+ return c.addNode(.{
+ .tag = .struct_init_dot_two_comma,
+ .main_token = l_brace,
+ .data = .{
+ .lhs = inits[0],
+ .rhs = inits[1],
+ },
+ });
+ } else {
+ const span = try c.listToSpan(inits);
+ return c.addNode(.{
+ .tag = .struct_init_dot_comma,
+ .main_token = l_brace,
+ .data = .{
+ .lhs = span.start,
+ .rhs = span.end,
+ },
+ });
+ }
+ },
.container_init => {
const payload = node.castTag(.container_init).?.data;
const lhs = try renderNode(c, payload.lhs);
@@ -2257,6 +2299,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.array_init,
.tuple,
.container_init,
+ .container_init_dot,
.block,
=> return c.addNode(.{
.tag = .grouped_expression,
src/translate_c.zig
@@ -4813,8 +4813,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
const br = blk_last.castTag(.break_val).?;
break :blk br.data.val;
} else expr;
- const return_type = if (typeof_arg.castTag(.std_meta_cast)) |some|
+
+ const return_type = if (typeof_arg.castTag(.std_meta_cast) orelse typeof_arg.castTag(.std_mem_zeroinit)) |some|
some.data.lhs
+ else if (typeof_arg.castTag(.std_mem_zeroes)) |some|
+ some.data
else
try Tag.typeof.create(c.arena, typeof_arg);
@@ -4932,6 +4935,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
}
},
.FloatLiteral => |suffix| {
+ if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1];
const dot_index = mem.indexOfScalar(u8, lit_bytes, '.').?;
if (dot_index == 0) {
lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
@@ -4943,15 +4947,16 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
lit_bytes[dot_index + 1 ..],
});
}
- if (suffix == .none) {
+
+ if (suffix == .none)
return transCreateNodeNumber(c, lit_bytes, .float);
- }
+
const type_node = try Tag.type.create(c.arena, switch (suffix) {
.f => "f32",
.l => "c_longdouble",
else => unreachable,
});
- const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1], .float);
+ const rhs = try transCreateNodeNumber(c, lit_bytes, .float);
return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
},
else => unreachable,
@@ -5540,6 +5545,42 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
}
},
.LBrace => {
+ // Check for designated field initializers
+ if (m.peek().? == .Period) {
+ var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa);
+ defer init_vals.deinit();
+
+ while (true) {
+ if (m.next().? != .Period) {
+ try m.fail(c, "unable to translate C expr: expected '.'", .{});
+ return error.ParseError;
+ }
+ if (m.next().? != .Identifier) {
+ try m.fail(c, "unable to translate C expr: expected identifier", .{});
+ return error.ParseError;
+ }
+ const name = m.slice();
+ if (m.next().? != .Equal) {
+ try m.fail(c, "unable to translate C expr: expected '='", .{});
+ return error.ParseError;
+ }
+
+ const val = try parseCCondExpr(c, m, scope);
+ try init_vals.append(.{ .name = name, .value = val });
+ switch (m.next().?) {
+ .Comma => {},
+ .RBrace => break,
+ else => {
+ try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});
+ return error.ParseError;
+ },
+ }
+ }
+ const tuple_node = try Tag.container_init_dot.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInitDot.Initializer, init_vals.items));
+ node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
+ continue;
+ }
+
var init_vals = std.ArrayList(Node).init(c.gpa);
defer init_vals.deinit();
test/translate_c.zig
@@ -336,6 +336,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ int i1;
\\} boom_t;
\\#define FOO ((boom_t){1})
+ \\typedef struct { float x; } MyCStruct;
+ \\#define A(_x) (MyCStruct) { .x = (_x) }
+ \\#define B A(0.f)
, &[_][]const u8{
\\pub const struct_Color = extern struct {
\\ r: u8,
@@ -357,6 +360,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const boom_t = struct_boom_t;
,
\\pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)});
+ ,
+ \\pub const MyCStruct = extern struct {
+ \\ x: f32,
+ \\};
+ ,
+ \\pub inline fn A(_x: anytype) MyCStruct {
+ \\ return @import("std").mem.zeroInit(MyCStruct, .{
+ \\ .x = _x,
+ \\ });
+ \\}
+ ,
+ \\pub const B = A(@as(f32, 0.0));
});
cases.add("complex switch",