| ... | ... | @@ -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. |
| 1 | 6 | const std = @import("std"); |
| 2 | 7 | const Type = @import("../type.zig").Type; |
| 3 | 8 | const Allocator = std.mem.Allocator; |
| ... | ... | @@ -840,18 +845,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 840 | 845 | .rhs = undefined, |
| 841 | 846 | }, |
| 842 | 847 | }), |
| 843 | | .@"continue" => { |
| 844 | | const tok = try c.addToken(.keyword_continue, "continue"); |
| 845 | | _ = try c.addToken(.semicolon, ";"); |
| 846 | | return c.addNode(.{ |
| 847 | | .tag = .@"continue", |
| 848 | | .main_token = tok, |
| 849 | | .data = .{ |
| 850 | | .lhs = 0, |
| 851 | | .rhs = undefined, |
| 852 | | }, |
| 853 | | }); |
| 854 | | }, |
| 848 | .@"continue" => return c.addNode(.{ |
| 849 | .tag = .@"continue", |
| 850 | .main_token = try c.addToken(.keyword_continue, "continue"), |
| 851 | .data = .{ |
| 852 | .lhs = 0, |
| 853 | .rhs = undefined, |
| 854 | }, |
| 855 | }), |
| 855 | 856 | .@"break" => { |
| 856 | 857 | const payload = node.castTag(.@"break").?.data; |
| 857 | 858 | const tok = try c.addToken(.keyword_break, "break"); |
| ... | ... | @@ -859,7 +860,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 859 | 860 | _ = try c.addToken(.colon, ":"); |
| 860 | 861 | break :blk try c.addIdentifier(some); |
| 861 | 862 | } else 0; |
| 862 | | _ = try c.addToken(.semicolon, ";"); |
| 863 | 863 | return c.addNode(.{ |
| 864 | 864 | .tag = .identifier, |
| 865 | 865 | .main_token = try c.addToken(.keyword_break, "break"), |
| ... | ... | @@ -876,14 +876,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 876 | 876 | _ = try c.addToken(.colon, ":"); |
| 877 | 877 | break :blk try c.addIdentifier(some); |
| 878 | 878 | } else 0; |
| 879 | | const val = try renderNode(c, payload.val); |
| 880 | | _ = try c.addToken(.semicolon, ";"); |
| 881 | 879 | return c.addNode(.{ |
| 882 | 880 | .tag = .identifier, |
| 883 | 881 | .main_token = try c.addToken(.keyword_break, "break"), |
| 884 | 882 | .data = .{ |
| 885 | 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 | 1167 | .array_cat => return renderBinOp(c, node, .array_cat, .plus_plus, "++"), |
| 1170 | 1168 | .ellipsis3 => return renderBinOp(c, node, .switch_range, .ellipsis3, "..."), |
| 1171 | 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 | 1248 | else => return c.addNode(.{ |
| 1173 | 1249 | .tag = .identifier, |
| 1174 | 1250 | .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}), |
| ... | ... | @@ -1555,3 +1631,156 @@ fn renderVar(c: *Context, node: Node) !NodeIndex { |
| 1555 | 1631 | }); |
| 1556 | 1632 | } |
| 1557 | 1633 | } |
| 1634 | |
| 1635 | fn 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 | } |