Commit 77a11e6873
Changed files (2)
src
translate_c
src/translate_c/ast.zig
@@ -520,7 +520,10 @@ pub const Payload = struct {
pub const ContainerInit = struct {
base: Payload,
- data: []Initializer,
+ data: struct {
+ lhs: Node,
+ inits: []Initializer,
+ },
pub const Initializer = struct {
name: []const u8,
@@ -1528,20 +1531,250 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const lhs = try renderNode(c, payload.lhs);
return renderFieldAccess(c, lhs, payload.field_name);
},
- .tuple,
- .@"enum",
- .@"struct",
- .@"union",
- .container_init,
- .enum_redecl,
- => return c.addNode(.{
- .tag = .identifier,
- .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}),
+ .@"struct", .@"union" => return renderRecord(c, node),
+ .@"enum" => {
+ const payload = node.castTag(.@"enum").?.data;
+ const enum_tok = try c.addToken(.keyword_enum, "enum");
+
+ _ = try c.addToken(.l_brace, "{");
+ const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.len + 1, 1));
+ defer c.gpa.free(members);
+ members[0] = 0;
+ members[1] = 0;
+
+ for (payload) |field, i| {
+ const name_tok = try c.addIdentifier(field.name);
+ const value_expr = if (field.value) |some| blk: {
+ _ = try c.addToken(.equal, "=");
+ break :blk try renderNode(c, some);
+ } else 0;
+
+ members[i] = try c.addNode(.{
+ .tag = .container_field_init,
+ .main_token = name_tok,
+ .data = .{
+ .lhs = 0,
+ .rhs = value_expr,
+ },
+ });
+ _ = try c.addToken(.comma, ",");
+ }
+ // make non-exhaustive
+ members[payload.len] = try c.addNode(.{
+ .tag = .container_field_init,
+ .main_token = try c.addIdentifier("_"),
+ .data = .{
+ .lhs = 0,
+ .rhs = 0,
+ },
+ });
+ _ = try c.addToken(.comma, ",");
+ _ = try c.addToken(.r_brace, "}");
+
+ if (members.len <= 2) {
+ return c.addNode(.{
+ .tag = .container_decl_two_comma,
+ .main_token = enum_tok,
+ .data = .{
+ .lhs = members[0],
+ .rhs = members[1],
+ },
+ });
+ } else {
+ const span = try c.listToSpan(members);
+ return c.addNode(.{
+ .tag = .container_decl_comma,
+ .main_token = enum_tok,
+ .data = .{
+ .lhs = span.start,
+ .rhs = span.end,
+ },
+ });
+ }
+ },
+ .enum_redecl => {
+ const payload = node.castTag(.enum_redecl).?.data;
+ _ = try c.addToken(.keyword_pub, "pub");
+ const const_tok = try c.addToken(.keyword_const, "const");
+ _ = try c.addIdentifier(payload.enum_val_name);
+ _ = try c.addToken(.equal, "=");
+
+ const enum_to_int_tok = try c.addToken(.builtin, "@enumToInt");
+ _ = try c.addToken(.l_paren, "(");
+ const enum_name = try c.addNode(.{
+ .tag = .identifier,
+ .main_token = try c.addIdentifier(payload.enum_name),
+ .data = undefined,
+ });
+ const field_access = try renderFieldAccess(c, enum_name, payload.field_name);
+ const init_node = try c.addNode(.{
+ .tag = .builtin_call_two,
+ .main_token = enum_to_int_tok,
+ .data = .{
+ .lhs = field_access,
+ .rhs = 0,
+ },
+ });
+ _ = try c.addToken(.r_paren, ")");
+ _ = try c.addToken(.semicolon, ";");
+
+ return c.addNode(.{
+ .tag = .simple_var_decl,
+ .main_token = const_tok,
+ .data = .{
+ .lhs = 0,
+ .rhs = init_node,
+ },
+ });
+ },
+ .tuple => {
+ const payload = node.castTag(.tuple).?.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, 1));
+ defer c.gpa.free(inits);
+ inits[0] = 0;
+ for (payload) |init, i| {
+ if (i != 0) _ = try c.addToken(.comma, ",");
+ inits[i] = try renderNode(c, init);
+ }
+ _ = try c.addToken(.r_brace, "}");
+ if (payload.len < 3) {
+ return c.addNode(.{
+ .tag = .array_init_dot_two,
+ .main_token = l_brace,
+ .data = .{
+ .lhs = inits[0],
+ .rhs = inits[1],
+ },
+ });
+ } else {
+ const span = try c.listToSpan(inits);
+ return c.addNode(.{
+ .tag = .array_init_dot,
+ .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);
+
+ const l_brace = try c.addToken(.l_brace, "{");
+ var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.inits.len, 1));
+ defer c.gpa.free(inits);
+ inits[0] = 0;
+ for (payload.inits) |init, i| {
+ if (i != 0) _ = try c.addToken(.comma, ",");
+ _ = try c.addToken(.period, ".");
+ _ = try c.addIdentifier(init.name);
+ _ = try c.addToken(.equal, "=");
+ inits[i] = try renderNode(c, init.value);
+ }
+ _ = try c.addToken(.r_brace, "}");
+
+ if (payload.inits.len < 2) {
+ return c.addNode(.{
+ .tag = .struct_init_one,
+ .main_token = l_brace,
+ .data = .{
+ .lhs = lhs,
+ .rhs = inits[0],
+ },
+ });
+ } else {
+ const span = try c.listToSpan(inits);
+ return c.addNode(.{
+ .tag = .struct_init,
+ .main_token = l_brace,
+ .data = .{
+ .lhs = lhs,
+ .rhs = try c.addExtra(NodeSubRange{
+ .start = span.start,
+ .end = span.end,
+ }),
+ },
+ });
+ }
+ },
+ }
+}
+
+fn renderRecord(c: *Context, node: Node) !NodeIndex {
+ const payload = @fieldParentPtr(Payload.Record, "base", node.ptr_otherwise).data;
+ if (payload.is_packed) _ = try c.addToken(.keyword_packed, "packed");
+ const kind_tok = if (node.tag() == .@"struct")
+ try c.addToken(.keyword_struct, "struct")
+ else
+ try c.addToken(.keyword_union, "union");
+
+ _ = try c.addToken(.l_brace, "{");
+ const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.fields.len, 2));
+ defer c.gpa.free(members);
+ members[0] = 0;
+ members[1] = 0;
+
+ for (payload.fields) |field, i| {
+ const name_tok = try c.addIdentifier(field.name);
+ _ = try c.addToken(.colon, ":");
+ const type_expr = try renderNode(c, field.type);
+
+ const alignment = field.alignment orelse {
+ members[i] = try c.addNode(.{
+ .tag = .container_field_init,
+ .main_token = name_tok,
+ .data = .{
+ .lhs = type_expr,
+ .rhs = 0,
+ },
+ });
+ _ = try c.addToken(.comma, ",");
+ continue;
+ };
+ _ = try c.addToken(.keyword_align, "align");
+ _ = try c.addToken(.l_paren, "(");
+ const align_expr = try c.addNode(.{
+ .tag = .integer_literal,
+ .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{alignment}),
+ .data = undefined,
+ });
+ _ = try c.addToken(.r_paren, ")");
+
+ members[i] = try c.addNode(.{
+ .tag = .container_field_align,
+ .main_token = name_tok,
.data = .{
- .lhs = undefined,
- .rhs = undefined,
+ .lhs = type_expr,
+ .rhs = align_expr,
},
- }),
+ });
+ _ = try c.addToken(.comma, ",");
+ }
+ _ = try c.addToken(.r_brace, "}");
+
+ if (members.len <= 2) {
+ return c.addNode(.{
+ .tag = .container_decl_two_comma,
+ .main_token = kind_tok,
+ .data = .{
+ .lhs = members[0],
+ .rhs = members[1],
+ },
+ });
+ } else {
+ const span = try c.listToSpan(members);
+ return c.addNode(.{
+ .tag = .container_decl_comma,
+ .main_token = kind_tok,
+ .data = .{
+ .lhs = span.start,
+ .rhs = span.end,
+ },
+ });
}
}
@@ -1558,50 +1791,37 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {
const l_brace = try c.addToken(.l_brace, "{");
- const res = switch (inits.len) {
- 0 => try c.addNode(.{
- .tag = .struct_init_one,
+ var rendered = try c.gpa.alloc(NodeIndex, std.math.max(inits.len, 1));
+ defer c.gpa.free(rendered);
+ rendered[0] = 0;
+ for (inits) |init, i| {
+ if (i != 0) _ = try c.addToken(.comma, ",");
+ rendered[i] = try renderNode(c, init);
+ }
+ _ = try c.addToken(.r_brace, "}");
+ if (inits.len < 2) {
+ return c.addNode(.{
+ .tag = .array_init_one,
.main_token = l_brace,
.data = .{
.lhs = lhs,
- .rhs = 0,
+ .rhs = rendered[0],
},
- }),
- 1 => blk: {
- const init = try renderNode(c, inits[0]);
- break :blk try c.addNode(.{
- .tag = .array_init_one,
- .main_token = l_brace,
- .data = .{
- .lhs = lhs,
- .rhs = init,
- },
- });
- },
- else => blk: {
- var rendered = try c.gpa.alloc(NodeIndex, inits.len);
- defer c.gpa.free(rendered);
-
- for (inits) |init, i| {
- if (i != 0) _ = try c.addToken(.comma, ",");
- rendered[i] = try renderNode(c, init);
- }
- const span = try c.listToSpan(rendered);
- break :blk try c.addNode(.{
- .tag = .array_init,
- .main_token = l_brace,
- .data = .{
- .lhs = lhs,
- .rhs = try c.addExtra(NodeSubRange{
- .start = span.start,
- .end = span.end,
- }),
- },
- });
- },
- };
- _ = try c.addToken(.r_brace, "}");
- return res;
+ });
+ } else {
+ const span = try c.listToSpan(rendered);
+ return c.addNode(.{
+ .tag = .array_init,
+ .main_token = l_brace,
+ .data = .{
+ .lhs = lhs,
+ .rhs = try c.addExtra(NodeSubRange{
+ .start = span.start,
+ .end = span.end,
+ }),
+ },
+ });
+ }
}
fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
src/translate_c.zig
@@ -1871,7 +1871,10 @@ fn transInitListExprRecord(
});
}
- return Tag.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));
+ return Tag.container_init.create(c.arena, .{
+ .lhs = ty_node,
+ .inits = try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items),
+ });
}
fn transInitListExprArray(