| ... | @@ -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. |
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const Type = @import("../type.zig").Type; | 7 | const Type = @import("../type.zig").Type; |
| 3 | const Allocator = std.mem.Allocator; | 8 | const 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 | |
| | 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 | } |