authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-13 22:53:24+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:42+02:00
logf191251ddb424eba7384d31fa2d50e50586f3993
treeddce021386fb869867010791588090e6bce1e9f4
parent227f167958ab37fe1df1b1dea5e3da42651b49c9
signature Commit is signed but in an unrecognized format.

translate-c: render functions


2 files changed, 246 insertions(+), 17 deletions(-)

src/translate_c.zig+1-1
...@@ -107,7 +107,7 @@ const Scope = struct {...@@ -107,7 +107,7 @@ const Scope = struct {
107 // do while, we want to put `if (cond) break;` at the end.107 // do while, we want to put `if (cond) break;` at the end.
108 const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .loop);108 const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .loop);
109 var stmts = try c.arena.alloc(Node, alloc_len);109 var stmts = try c.arena.alloc(Node, alloc_len);
110 stmts.len -= 1;110 stmts.len = self.statements.items.len;
111 mem.copy(Node, stmts, self.statements.items);111 mem.copy(Node, stmts, self.statements.items);
112 return Tag.block.create(c.arena, .{112 return Tag.block.create(c.arena, .{
113 .label = self.label,113 .label = self.label,
src/translate_c/ast.zig+245-16
...@@ -1,3 +1,8 @@...@@ -1,3 +1,8 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2021 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
1const std = @import("std");6const std = @import("std");
2const Type = @import("../type.zig").Type;7const Type = @import("../type.zig").Type;
3const Allocator = std.mem.Allocator;8const Allocator = std.mem.Allocator;
...@@ -840,18 +845,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -840,18 +845,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
840 .rhs = undefined,845 .rhs = undefined,
841 },846 },
842 }),847 }),
843 .@"continue" => {848 .@"continue" => return c.addNode(.{
844 const tok = try c.addToken(.keyword_continue, "continue");849 .tag = .@"continue",
845 _ = try c.addToken(.semicolon, ";");850 .main_token = try c.addToken(.keyword_continue, "continue"),
846 return c.addNode(.{851 .data = .{
847 .tag = .@"continue",852 .lhs = 0,
848 .main_token = tok,853 .rhs = undefined,
849 .data = .{854 },
850 .lhs = 0,855 }),
851 .rhs = undefined,
852 },
853 });
854 },
855 .@"break" => {856 .@"break" => {
856 const payload = node.castTag(.@"break").?.data;857 const payload = node.castTag(.@"break").?.data;
857 const tok = try c.addToken(.keyword_break, "break");858 const tok = try c.addToken(.keyword_break, "break");
...@@ -859,7 +860,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -859,7 +860,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
859 _ = try c.addToken(.colon, ":");860 _ = try c.addToken(.colon, ":");
860 break :blk try c.addIdentifier(some);861 break :blk try c.addIdentifier(some);
861 } else 0;862 } else 0;
862 _ = try c.addToken(.semicolon, ";");
863 return c.addNode(.{863 return c.addNode(.{
864 .tag = .identifier,864 .tag = .identifier,
865 .main_token = try c.addToken(.keyword_break, "break"),865 .main_token = try c.addToken(.keyword_break, "break"),
...@@ -876,14 +876,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -876,14 +876,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
876 _ = try c.addToken(.colon, ":");876 _ = try c.addToken(.colon, ":");
877 break :blk try c.addIdentifier(some);877 break :blk try c.addIdentifier(some);
878 } else 0;878 } else 0;
879 const val = try renderNode(c, payload.val);
880 _ = try c.addToken(.semicolon, ";");
881 return c.addNode(.{879 return c.addNode(.{
882 .tag = .identifier,880 .tag = .identifier,
883 .main_token = try c.addToken(.keyword_break, "break"),881 .main_token = try c.addToken(.keyword_break, "break"),
884 .data = .{882 .data = .{
885 .lhs = break_label,883 .lhs = break_label,
886 .rhs = val,884 .rhs = try renderNode(c, payload.val),
887 },885 },
888 });886 });
889 },887 },
...@@ -1169,6 +1167,84 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1169,6 +1167,84 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1169 .array_cat => return renderBinOp(c, node, .array_cat, .plus_plus, "++"),1167 .array_cat => return renderBinOp(c, node, .array_cat, .plus_plus, "++"),
1170 .ellipsis3 => return renderBinOp(c, node, .switch_range, .ellipsis3, "..."),1168 .ellipsis3 => return renderBinOp(c, node, .switch_range, .ellipsis3, "..."),
1171 .assign => return renderBinOp(c, node, .assign, .equal, "="),1169 .assign => return renderBinOp(c, node, .assign, .equal, "="),
1170 .empty_block => {
1171 const l_brace = try c.addToken(.l_brace, "{");
1172 _ = try c.addToken(.r_brace, "}");
1173 return c.addNode(.{
1174 .tag = .block_two,
1175 .main_token = l_brace,
1176 .data = .{
1177 .lhs = 0,
1178 .rhs = 0,
1179 },
1180 });
1181 },
1182 .block_single => {
1183 const payload = node.castTag(.block_single).?.data;
1184 const l_brace = try c.addToken(.l_brace, "{");
1185
1186 const stmt = try renderNode(c, payload);
1187 _ = try c.addToken(.semicolon, ";");
1188
1189 _ = try c.addToken(.r_brace, "}");
1190 return c.addNode(.{
1191 .tag = .block_two,
1192 .main_token = l_brace,
1193 .data = .{
1194 .lhs = stmt,
1195 .rhs = 0,
1196 },
1197 });
1198 },
1199 .block => {
1200 const payload = node.castTag(.block).?.data;
1201 if (payload.label) |some| {
1202 _ = try c.addIdentifier(some);
1203 _ = try c.addToken(.colon, ":");
1204 }
1205 const l_brace = try c.addToken(.l_brace, "{");
1206
1207 var stmts = std.ArrayList(NodeIndex).init(c.gpa);
1208 defer stmts.deinit();
1209 for (payload.stmts) |stmt| {
1210 const res = try renderNode(c, stmt);
1211 switch (stmt.tag()) {
1212 .warning => continue,
1213 .var_decl, .var_simple => {},
1214 else => _ = try c.addToken(.semicolon, ";"),
1215 }
1216 try stmts.append(res);
1217 }
1218 const span = try c.listToSpan(stmts.items);
1219 _ = try c.addToken(.r_brace, "}");
1220
1221 const semicolon = c.tokens.items(.tag)[c.tokens.len - 2] == .semicolon;
1222 return c.addNode(.{
1223 .tag = if (semicolon) .block_semicolon else .block,
1224 .main_token = l_brace,
1225 .data = .{
1226 .lhs = span.start,
1227 .rhs = span.end,
1228 },
1229 });
1230 },
1231 .func => return renderFunc(c, node),
1232 .discard => {
1233 const payload = node.castTag(.discard).?.data;
1234 const lhs = try c.addNode(.{
1235 .tag = .identifier,
1236 .main_token = try c.addToken(.identifier, "_"),
1237 .data = .{ .lhs = undefined, .rhs = undefined },
1238 });
1239 return c.addNode(.{
1240 .tag = .assign,
1241 .main_token = try c.addToken(.equal, "="),
1242 .data = .{
1243 .lhs = lhs,
1244 .rhs = try renderNode(c, payload),
1245 },
1246 });
1247 },
1172 else => return c.addNode(.{1248 else => return c.addNode(.{
1173 .tag = .identifier,1249 .tag = .identifier,
1174 .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}),1250 .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}),
...@@ -1555,3 +1631,156 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {...@@ -1555,3 +1631,156 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
1555 });1631 });
1556 }1632 }
1557}1633}
1634
1635fn renderFunc(c: *Context, node: Node) !NodeIndex {
1636 const payload = node.castTag(.func).?.data;
1637 if (payload.is_pub) _ = try c.addToken(.keyword_pub, "pub");
1638 if (payload.is_extern) _ = try c.addToken(.keyword_extern, "extern");
1639 if (payload.is_export) _ = try c.addToken(.keyword_export, "export");
1640 const fn_token = try c.addToken(.keyword_fn, "fn");
1641 if (payload.name) |some| _ = try c.addIdentifier(some);
1642
1643 _ = try c.addToken(.l_paren, "(");
1644 const first = if (payload.params.len != 0) blk: {
1645 const param = payload.params[0];
1646 if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
1647 if (param.name) |some| {
1648 _ = try c.addIdentifier(some);
1649 _ = try c.addToken(.colon, ":");
1650 }
1651 break :blk try renderNode(c, param.type);
1652 } else 0;
1653
1654 var span: NodeSubRange = undefined;
1655 if (payload.params.len > 1) {
1656 var params = std.ArrayList(NodeIndex).init(c.gpa);
1657 defer params.deinit();
1658
1659 try params.append(first);
1660 for (payload.params[1..]) |param| {
1661 _ = try c.addToken(.comma, ",");
1662 if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
1663 if (param.name) |some| {
1664 _ = try c.addIdentifier(some);
1665 _ = try c.addToken(.colon, ":");
1666 }
1667 try params.append(try renderNode(c, param.type));
1668 }
1669 span = try c.listToSpan(params.items);
1670 }
1671 if (payload.is_var_args) {
1672 if (payload.params.len != 0) _ = try c.addToken(.comma, ",");
1673 _ = try c.addToken(.ellipsis3, "...");
1674 }
1675 _ = try c.addToken(.r_paren, ")");
1676
1677 const return_type_expr = try renderNode(c, payload.return_type);
1678
1679 const align_expr = if (payload.alignment) |some| blk: {
1680 _ = try c.addToken(.keyword_align, "align");
1681 _ = try c.addToken(.l_paren, "(");
1682 const res = try c.addNode(.{
1683 .tag = .integer_literal,
1684 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
1685 .data = .{ .lhs = undefined, .rhs = undefined },
1686 });
1687 _ = try c.addToken(.r_paren, ")");
1688 break :blk res;
1689 } else 0;
1690
1691 const section_expr = if (payload.linksection_string) |some| blk: {
1692 _ = try c.addToken(.keyword_linksection, "linksection");
1693 _ = try c.addToken(.l_paren, "(");
1694 const res = try c.addNode(.{
1695 .tag = .string_literal,
1696 .main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),
1697 .data = .{ .lhs = undefined, .rhs = undefined },
1698 });
1699 _ = try c.addToken(.r_paren, ")");
1700 break :blk res;
1701 } else 0;
1702
1703 const callconv_expr = if (payload.explicit_callconv) |some| blk: {
1704 _ = try c.addToken(.keyword_linksection, "callconv");
1705 _ = try c.addToken(.l_paren, "(");
1706 _ = try c.addToken(.period, ".");
1707 const res = try c.addNode(.{
1708 .tag = .enum_literal,
1709 .main_token = try c.addTokenFmt(.string_literal, "{}", .{some}),
1710 .data = .{ .lhs = undefined, .rhs = undefined },
1711 });
1712 _ = try c.addToken(.r_paren, ")");
1713 break :blk res;
1714 } else 0;
1715
1716 const fn_proto = try blk: {
1717 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
1718 if (payload.params.len < 2)
1719 break :blk c.addNode(.{
1720 .tag = .fn_proto_simple,
1721 .main_token = fn_token,
1722 .data = .{
1723 .lhs = first,
1724 .rhs = return_type_expr,
1725 },
1726 })
1727 else
1728 break :blk c.addNode(.{
1729 .tag = .fn_proto_multi,
1730 .main_token = fn_token,
1731 .data = .{
1732 .lhs = try c.addExtra(std.zig.ast.Node.SubRange{
1733 .start = span.start,
1734 .end = span.end,
1735 }),
1736 .rhs = return_type_expr,
1737 },
1738 });
1739 }
1740 if (payload.params.len < 2)
1741 break :blk c.addNode(.{
1742 .tag = .fn_proto_one,
1743 .main_token = fn_token,
1744 .data = .{
1745 .lhs = try c.addExtra(std.zig.ast.Node.FnProtoOne{
1746 .param = first,
1747 .align_expr = align_expr,
1748 .section_expr = section_expr,
1749 .callconv_expr = callconv_expr,
1750 }),
1751 .rhs = return_type_expr,
1752 },
1753 })
1754 else
1755 break :blk c.addNode(.{
1756 .tag = .fn_proto,
1757 .main_token = fn_token,
1758 .data = .{
1759 .lhs = try c.addExtra(std.zig.ast.Node.FnProto{
1760 .params_start = span.start,
1761 .params_end = span.end,
1762 .align_expr = align_expr,
1763 .section_expr = section_expr,
1764 .callconv_expr = callconv_expr,
1765 }),
1766 .rhs = return_type_expr,
1767 },
1768 });
1769 };
1770
1771 const body = if (payload.body) |some|
1772 try renderNode(c, some)
1773 else blk: {
1774 _ = try c.addToken(.semicolon, ";");
1775 break :blk 0;
1776 };
1777
1778 return c.addNode(.{
1779 .tag = .fn_decl,
1780 .main_token = fn_token,
1781 .data = .{
1782 .lhs = fn_proto,
1783 .rhs = body,
1784 },
1785 });
1786}