mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
translate-c: support designated initializers in macros
This commit is contained in:
parent
99b6305aa8
commit
c6a0a4e728
@ -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();
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user