authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-15 13:27:14+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:43+02:00
log77a11e6873d0f30950d8a523c990d32b5a25a658
treeefc9552d9f0b868e9bc75fdc99d2741e852076ce
parentc0540967e974b59bf85f71be9f085b5852d20ef6
signature Commit is signed but in an unrecognized format.

translate-c: render records and enums


2 files changed, 277 insertions(+), 54 deletions(-)

src/translate_c.zig+4-1
...@@ -1871,7 +1871,10 @@ fn transInitListExprRecord(...@@ -1871,7 +1871,10 @@ fn transInitListExprRecord(
1871 });1871 });
1872 }1872 }
18731873
1874 return Tag.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));1874 return Tag.container_init.create(c.arena, .{
1875 .lhs = ty_node,
1876 .inits = try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items),
1877 });
1875}1878}
18761879
1877fn transInitListExprArray(1880fn transInitListExprArray(
src/translate_c/ast.zig+273-53
...@@ -520,7 +520,10 @@ pub const Payload = struct {...@@ -520,7 +520,10 @@ pub const Payload = struct {
520520
521 pub const ContainerInit = struct {521 pub const ContainerInit = struct {
522 base: Payload,522 base: Payload,
523 data: []Initializer,523 data: struct {
524 lhs: Node,
525 inits: []Initializer,
526 },
524527
525 pub const Initializer = struct {528 pub const Initializer = struct {
526 name: []const u8,529 name: []const u8,
...@@ -1528,20 +1531,250 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1528,20 +1531,250 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1528 const lhs = try renderNode(c, payload.lhs);1531 const lhs = try renderNode(c, payload.lhs);
1529 return renderFieldAccess(c, lhs, payload.field_name);1532 return renderFieldAccess(c, lhs, payload.field_name);
1530 },1533 },
1531 .tuple,1534 .@"struct", .@"union" => return renderRecord(c, node),
1532 .@"enum",1535 .@"enum" => {
1533 .@"struct",1536 const payload = node.castTag(.@"enum").?.data;
1534 .@"union",1537 const enum_tok = try c.addToken(.keyword_enum, "enum");
1535 .container_init,1538
1536 .enum_redecl,1539 _ = try c.addToken(.l_brace, "{");
1537 => return c.addNode(.{1540 const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.len + 1, 1));
1538 .tag = .identifier,1541 defer c.gpa.free(members);
1539 .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}),1542 members[0] = 0;
1543 members[1] = 0;
1544
1545 for (payload) |field, i| {
1546 const name_tok = try c.addIdentifier(field.name);
1547 const value_expr = if (field.value) |some| blk: {
1548 _ = try c.addToken(.equal, "=");
1549 break :blk try renderNode(c, some);
1550 } else 0;
1551
1552 members[i] = try c.addNode(.{
1553 .tag = .container_field_init,
1554 .main_token = name_tok,
1555 .data = .{
1556 .lhs = 0,
1557 .rhs = value_expr,
1558 },
1559 });
1560 _ = try c.addToken(.comma, ",");
1561 }
1562 // make non-exhaustive
1563 members[payload.len] = try c.addNode(.{
1564 .tag = .container_field_init,
1565 .main_token = try c.addIdentifier("_"),
1566 .data = .{
1567 .lhs = 0,
1568 .rhs = 0,
1569 },
1570 });
1571 _ = try c.addToken(.comma, ",");
1572 _ = try c.addToken(.r_brace, "}");
1573
1574 if (members.len <= 2) {
1575 return c.addNode(.{
1576 .tag = .container_decl_two_comma,
1577 .main_token = enum_tok,
1578 .data = .{
1579 .lhs = members[0],
1580 .rhs = members[1],
1581 },
1582 });
1583 } else {
1584 const span = try c.listToSpan(members);
1585 return c.addNode(.{
1586 .tag = .container_decl_comma,
1587 .main_token = enum_tok,
1588 .data = .{
1589 .lhs = span.start,
1590 .rhs = span.end,
1591 },
1592 });
1593 }
1594 },
1595 .enum_redecl => {
1596 const payload = node.castTag(.enum_redecl).?.data;
1597 _ = try c.addToken(.keyword_pub, "pub");
1598 const const_tok = try c.addToken(.keyword_const, "const");
1599 _ = try c.addIdentifier(payload.enum_val_name);
1600 _ = try c.addToken(.equal, "=");
1601
1602 const enum_to_int_tok = try c.addToken(.builtin, "@enumToInt");
1603 _ = try c.addToken(.l_paren, "(");
1604 const enum_name = try c.addNode(.{
1605 .tag = .identifier,
1606 .main_token = try c.addIdentifier(payload.enum_name),
1607 .data = undefined,
1608 });
1609 const field_access = try renderFieldAccess(c, enum_name, payload.field_name);
1610 const init_node = try c.addNode(.{
1611 .tag = .builtin_call_two,
1612 .main_token = enum_to_int_tok,
1613 .data = .{
1614 .lhs = field_access,
1615 .rhs = 0,
1616 },
1617 });
1618 _ = try c.addToken(.r_paren, ")");
1619 _ = try c.addToken(.semicolon, ";");
1620
1621 return c.addNode(.{
1622 .tag = .simple_var_decl,
1623 .main_token = const_tok,
1624 .data = .{
1625 .lhs = 0,
1626 .rhs = init_node,
1627 },
1628 });
1629 },
1630 .tuple => {
1631 const payload = node.castTag(.tuple).?.data;
1632 _ = try c.addToken(.period, ".");
1633 const l_brace = try c.addToken(.l_brace, "{");
1634 var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.len, 1));
1635 defer c.gpa.free(inits);
1636 inits[0] = 0;
1637 for (payload) |init, i| {
1638 if (i != 0) _ = try c.addToken(.comma, ",");
1639 inits[i] = try renderNode(c, init);
1640 }
1641 _ = try c.addToken(.r_brace, "}");
1642 if (payload.len < 3) {
1643 return c.addNode(.{
1644 .tag = .array_init_dot_two,
1645 .main_token = l_brace,
1646 .data = .{
1647 .lhs = inits[0],
1648 .rhs = inits[1],
1649 },
1650 });
1651 } else {
1652 const span = try c.listToSpan(inits);
1653 return c.addNode(.{
1654 .tag = .array_init_dot,
1655 .main_token = l_brace,
1656 .data = .{
1657 .lhs = span.start,
1658 .rhs = span.end,
1659 },
1660 });
1661 }
1662 },
1663 .container_init => {
1664 const payload = node.castTag(.container_init).?.data;
1665 const lhs = try renderNode(c, payload.lhs);
1666
1667 const l_brace = try c.addToken(.l_brace, "{");
1668 var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.inits.len, 1));
1669 defer c.gpa.free(inits);
1670 inits[0] = 0;
1671 for (payload.inits) |init, i| {
1672 if (i != 0) _ = try c.addToken(.comma, ",");
1673 _ = try c.addToken(.period, ".");
1674 _ = try c.addIdentifier(init.name);
1675 _ = try c.addToken(.equal, "=");
1676 inits[i] = try renderNode(c, init.value);
1677 }
1678 _ = try c.addToken(.r_brace, "}");
1679
1680 if (payload.inits.len < 2) {
1681 return c.addNode(.{
1682 .tag = .struct_init_one,
1683 .main_token = l_brace,
1684 .data = .{
1685 .lhs = lhs,
1686 .rhs = inits[0],
1687 },
1688 });
1689 } else {
1690 const span = try c.listToSpan(inits);
1691 return c.addNode(.{
1692 .tag = .struct_init,
1693 .main_token = l_brace,
1694 .data = .{
1695 .lhs = lhs,
1696 .rhs = try c.addExtra(NodeSubRange{
1697 .start = span.start,
1698 .end = span.end,
1699 }),
1700 },
1701 });
1702 }
1703 },
1704 }
1705}
1706
1707fn renderRecord(c: *Context, node: Node) !NodeIndex {
1708 const payload = @fieldParentPtr(Payload.Record, "base", node.ptr_otherwise).data;
1709 if (payload.is_packed) _ = try c.addToken(.keyword_packed, "packed");
1710 const kind_tok = if (node.tag() == .@"struct")
1711 try c.addToken(.keyword_struct, "struct")
1712 else
1713 try c.addToken(.keyword_union, "union");
1714
1715 _ = try c.addToken(.l_brace, "{");
1716 const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.fields.len, 2));
1717 defer c.gpa.free(members);
1718 members[0] = 0;
1719 members[1] = 0;
1720
1721 for (payload.fields) |field, i| {
1722 const name_tok = try c.addIdentifier(field.name);
1723 _ = try c.addToken(.colon, ":");
1724 const type_expr = try renderNode(c, field.type);
1725
1726 const alignment = field.alignment orelse {
1727 members[i] = try c.addNode(.{
1728 .tag = .container_field_init,
1729 .main_token = name_tok,
1730 .data = .{
1731 .lhs = type_expr,
1732 .rhs = 0,
1733 },
1734 });
1735 _ = try c.addToken(.comma, ",");
1736 continue;
1737 };
1738 _ = try c.addToken(.keyword_align, "align");
1739 _ = try c.addToken(.l_paren, "(");
1740 const align_expr = try c.addNode(.{
1741 .tag = .integer_literal,
1742 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{alignment}),
1743 .data = undefined,
1744 });
1745 _ = try c.addToken(.r_paren, ")");
1746
1747 members[i] = try c.addNode(.{
1748 .tag = .container_field_align,
1749 .main_token = name_tok,
1540 .data = .{1750 .data = .{
1541 .lhs = undefined,1751 .lhs = type_expr,
1542 .rhs = undefined,1752 .rhs = align_expr,
1543 },1753 },
1544 }),1754 });
1755 _ = try c.addToken(.comma, ",");
1756 }
1757 _ = try c.addToken(.r_brace, "}");
1758
1759 if (members.len <= 2) {
1760 return c.addNode(.{
1761 .tag = .container_decl_two_comma,
1762 .main_token = kind_tok,
1763 .data = .{
1764 .lhs = members[0],
1765 .rhs = members[1],
1766 },
1767 });
1768 } else {
1769 const span = try c.listToSpan(members);
1770 return c.addNode(.{
1771 .tag = .container_decl_comma,
1772 .main_token = kind_tok,
1773 .data = .{
1774 .lhs = span.start,
1775 .rhs = span.end,
1776 },
1777 });
1545 }1778 }
1546}1779}
15471780
...@@ -1558,50 +1791,37 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI...@@ -1558,50 +1791,37 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
15581791
1559fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {1792fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {
1560 const l_brace = try c.addToken(.l_brace, "{");1793 const l_brace = try c.addToken(.l_brace, "{");
1561 const res = switch (inits.len) {1794 var rendered = try c.gpa.alloc(NodeIndex, std.math.max(inits.len, 1));
1562 0 => try c.addNode(.{1795 defer c.gpa.free(rendered);
1563 .tag = .struct_init_one,1796 rendered[0] = 0;
1797 for (inits) |init, i| {
1798 if (i != 0) _ = try c.addToken(.comma, ",");
1799 rendered[i] = try renderNode(c, init);
1800 }
1801 _ = try c.addToken(.r_brace, "}");
1802 if (inits.len < 2) {
1803 return c.addNode(.{
1804 .tag = .array_init_one,
1564 .main_token = l_brace,1805 .main_token = l_brace,
1565 .data = .{1806 .data = .{
1566 .lhs = lhs,1807 .lhs = lhs,
1567 .rhs = 0,1808 .rhs = rendered[0],
1568 },1809 },
1569 }),1810 });
1570 1 => blk: {1811 } else {
1571 const init = try renderNode(c, inits[0]);1812 const span = try c.listToSpan(rendered);
1572 break :blk try c.addNode(.{1813 return c.addNode(.{
1573 .tag = .array_init_one,1814 .tag = .array_init,
1574 .main_token = l_brace,1815 .main_token = l_brace,
1575 .data = .{1816 .data = .{
1576 .lhs = lhs,1817 .lhs = lhs,
1577 .rhs = init,1818 .rhs = try c.addExtra(NodeSubRange{
1578 },1819 .start = span.start,
1579 });1820 .end = span.end,
1580 },1821 }),
1581 else => blk: {1822 },
1582 var rendered = try c.gpa.alloc(NodeIndex, inits.len);1823 });
1583 defer c.gpa.free(rendered);1824 }
1584
1585 for (inits) |init, i| {
1586 if (i != 0) _ = try c.addToken(.comma, ",");
1587 rendered[i] = try renderNode(c, init);
1588 }
1589 const span = try c.listToSpan(rendered);
1590 break :blk try c.addNode(.{
1591 .tag = .array_init,
1592 .main_token = l_brace,
1593 .data = .{
1594 .lhs = lhs,
1595 .rhs = try c.addExtra(NodeSubRange{
1596 .start = span.start,
1597 .end = span.end,
1598 }),
1599 },
1600 });
1601 },
1602 };
1603 _ = try c.addToken(.r_brace, "}");
1604 return res;
1605}1825}
16061826
1607fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {1827fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {