| ... | @@ -24,6 +24,7 @@ nodes: Ast.NodeList, | ... | @@ -24,6 +24,7 @@ nodes: Ast.NodeList, |
| 24 | extra_data: std.ArrayList(u32), | 24 | extra_data: std.ArrayList(u32), |
| 25 | scratch: std.ArrayList(Node.Index), | 25 | scratch: std.ArrayList(Node.Index), |
| 26 | recover: bool, | 26 | recover: bool, |
| | 27 | use_old_precedence: bool = false, |
| 27 | | 28 | |
| 28 | fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag { | 29 | fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag { |
| 29 | return p.tokens.items(.tag)[token_index]; | 30 | return p.tokens.items(.tag)[token_index]; |
| ... | @@ -1531,6 +1532,8 @@ const PrecClass = struct { | ... | @@ -1531,6 +1532,8 @@ const PrecClass = struct { |
| 1531 | const Group = enum { | 1532 | const Group = enum { |
| 1532 | const num_distinct = std.meta.fieldNames(Group).len; | 1533 | const num_distinct = std.meta.fieldNames(Group).len; |
| 1533 | | 1534 | |
| | 1535 | top, |
| | 1536 | |
| 1534 | arithmetic_product_chainable, | 1537 | arithmetic_product_chainable, |
| 1535 | arithmetic_mod_nonchainable, | 1538 | arithmetic_mod_nonchainable, |
| 1536 | arithmetic_sum, | 1539 | arithmetic_sum, |
| ... | @@ -1588,7 +1591,7 @@ const PrecClass = struct { | ... | @@ -1588,7 +1591,7 @@ const PrecClass = struct { |
| 1588 | gt = 1, | 1591 | gt = 1, |
| 1589 | | 1592 | |
| 1590 | fn inverted(self: Rel) Rel { | 1593 | fn inverted(self: Rel) Rel { |
| 1591 | return @enumFromInt(-@intFromEnum(self)); | 1594 | return @fromBackingInt(@intCast(-@backingInt(self))); |
| 1592 | } | 1595 | } |
| 1593 | }; | 1596 | }; |
| 1594 | | 1597 | |
| ... | @@ -1602,12 +1605,14 @@ const PrecClass = struct { | ... | @@ -1602,12 +1605,14 @@ const PrecClass = struct { |
| 1602 | if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue; | 1605 | if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue; |
| 1603 | | 1606 | |
| 1604 | prec_array.*[i][j] = rel; | 1607 | prec_array.*[i][j] = rel; |
| | 1608 | prec_array.*[j][i] = rel.inverted(); |
| 1605 | } | 1609 | } |
| 1606 | } | 1610 | } |
| 1607 | } | 1611 | } |
| 1608 | | 1612 | |
| 1609 | fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void { | 1613 | fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void { |
| 1610 | prec_array.*[@intFromEnum(minor_a)][@intFromEnum(minor_b)] = rel; | 1614 | prec_array.*[@backingInt(minor_a)][@backingInt(minor_b)] = rel; |
| | 1615 | prec_array.*[@backingInt(minor_b)][@backingInt(minor_a)] = rel.inverted(); |
| 1611 | } | 1616 | } |
| 1612 | | 1617 | |
| 1613 | /// Arithmetic_* > Comparison | 1618 | /// Arithmetic_* > Comparison |
| ... | @@ -1622,6 +1627,9 @@ const PrecClass = struct { | ... | @@ -1622,6 +1627,9 @@ const PrecClass = struct { |
| 1622 | @setEvalBranchQuota(20_000); | 1627 | @setEvalBranchQuota(20_000); |
| 1623 | const major_greater_than_relations = [_][2]Group.Major{ | 1628 | const major_greater_than_relations = [_][2]Group.Major{ |
| 1624 | // zig fmt: off | 1629 | // zig fmt: off |
| | 1630 | .{ .top, .arithmetic }, |
| | 1631 | .{ .top, .bitwise }, |
| | 1632 | .{ .top, .recovery }, |
| 1625 | .{ .arithmetic, .comparison }, | 1633 | .{ .arithmetic, .comparison }, |
| 1626 | .{ .bitwise, .comparison }, | 1634 | .{ .bitwise, .comparison }, |
| 1627 | .{ .comparison, .bool }, | 1635 | .{ .comparison, .bool }, |
| ... | @@ -1656,30 +1664,21 @@ const PrecClass = struct { | ... | @@ -1656,30 +1664,21 @@ const PrecClass = struct { |
| 1656 | | 1664 | |
| 1657 | var order: PrecedenceArray = @splat(@splat(null)); | 1665 | var order: PrecedenceArray = @splat(@splat(null)); |
| 1658 | | 1666 | |
| | 1667 | setMinorRelation(&order, .top, .gt, .arithmetic_product_chainable); |
| | 1668 | |
| 1659 | setMinorRelation(&order, .arithmetic_product_chainable, .eq, .arithmetic_mod_nonchainable); | 1669 | setMinorRelation(&order, .arithmetic_product_chainable, .eq, .arithmetic_mod_nonchainable); |
| 1660 | setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum); | 1670 | setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum); |
| 1661 | setMinorRelation(&order, .arithmetic_product_chainable, .gt, .arithmetic_sum); | | |
| 1662 | | 1671 | |
| 1663 | setMinorRelation(&order, .arithmetic_sum, .gt, .bitwise_shift); | 1672 | setMinorRelation(&order, .arithmetic_sum, .gt, .bitwise_shift); |
| 1664 | | 1673 | |
| 1665 | // Here since the transative ordering computer cant leverage equals to derive a = b < c --> a < c, we have to manually list these | | |
| 1666 | setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_and); | 1674 | setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_and); |
| 1667 | setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_xor); | | |
| 1668 | setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_or); | | |
| 1669 | setMinorRelation(&order, .bitwise_shift, .gt, .recovery_catch); | | |
| 1670 | setMinorRelation(&order, .bitwise_shift, .gt, .recovery_orelse); | | |
| 1671 | | 1675 | |
| 1672 | setMinorRelation(&order, .bitwise_and, .eq, .bitwise_xor); | 1676 | setMinorRelation(&order, .bitwise_and, .eq, .bitwise_xor); |
| 1673 | setMinorRelation(&order, .bitwise_xor, .eq, .bitwise_or); | 1677 | setMinorRelation(&order, .bitwise_and, .eq, .bitwise_or); |
| 1674 | setMinorRelation(&order, .bitwise_or, .eq, .recovery_catch); | 1678 | setMinorRelation(&order, .bitwise_and, .eq, .recovery_catch); |
| 1675 | setMinorRelation(&order, .recovery_catch, .eq, .recovery_orelse); | 1679 | setMinorRelation(&order, .bitwise_and, .eq, .recovery_orelse); |
| 1676 | setMinorRelation(&order, .recovery_orelse, .eq, .bitwise_and); | | |
| 1677 | | 1680 | |
| 1678 | setMinorRelation(&order, .bitwise_and, .gt, .comparison); | 1681 | setMinorRelation(&order, .bitwise_and, .gt, .comparison); |
| 1679 | setMinorRelation(&order, .bitwise_xor, .gt, .comparison); | | |
| 1680 | setMinorRelation(&order, .bitwise_or, .gt, .comparison); | | |
| 1681 | setMinorRelation(&order, .recovery_catch, .gt, .comparison); | | |
| 1682 | setMinorRelation(&order, .recovery_orelse, .gt, .comparison); | | |
| 1683 | | 1682 | |
| 1684 | setMinorRelation(&order, .comparison, .gt, .bool_and); | 1683 | setMinorRelation(&order, .comparison, .gt, .bool_and); |
| 1685 | | 1684 | |
| ... | @@ -1697,16 +1696,22 @@ const PrecClass = struct { | ... | @@ -1697,16 +1696,22 @@ const PrecClass = struct { |
| 1697 | }; | 1696 | }; |
| 1698 | | 1697 | |
| 1699 | pub fn cmp(lhs: PrecClass, rhs: PrecClass) ?Rel { | 1698 | pub fn cmp(lhs: PrecClass, rhs: PrecClass) ?Rel { |
| 1700 | return PrecClass.precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)]; | 1699 | return PrecClass.precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)]; |
| 1701 | } | 1700 | } |
| 1702 | | 1701 | |
| 1703 | pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { | 1702 | pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { |
| 1704 | return PrecClass.v16_precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)].?; | 1703 | return PrecClass.v16_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?; |
| 1705 | } | 1704 | } |
| 1706 | | 1705 | |
| 1707 | fn computeTransativeOrdering(order: *PrecedenceArray) void { | 1706 | fn computeTransativeOrdering(order: *PrecedenceArray) void { |
| 1708 | for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| { | 1707 | for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| { |
| 1709 | if (order[i][k] == order[k][j] and order[i][k] != null) order[i][j] = order[i][k]; | 1708 | if (order[i][j] == null or order[j][k] == null) continue; |
| | 1709 | // X < Y < Z ==> X < Z X > Y > Z ==> X > Z |
| | 1710 | if (order[i][j] == order[j][k]) order[i][k] = order[i][j]; |
| | 1711 | // X = Y < Z ==> X < Z X = Y > Z ==> X > Z |
| | 1712 | if (order[i][j] == .eq) order[i][k] = order[j][k]; |
| | 1713 | // X < Y = Z ==> X < Z X > Y = Z ==> X > Z |
| | 1714 | if (order[j][k] == .eq) order[i][k] = order[i][j]; |
| 1710 | }; | 1715 | }; |
| 1711 | for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| { | 1716 | for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| { |
| 1712 | if (i == j) order[i][j] = .eq; | 1717 | if (i == j) order[i][j] = .eq; |
| ... | @@ -1762,6 +1767,23 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec | ... | @@ -1762,6 +1767,23 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec |
| 1762 | // zig fmt: on | 1767 | // zig fmt: on |
| 1763 | }); | 1768 | }); |
| 1764 | | 1769 | |
| | 1770 | fn comptimePrecedenceFromNodeTag(comptime tag: Node.Tag) PrecClass { |
| | 1771 | for (operTable) |data| { |
| | 1772 | if (data.tag == tag) return data.prec; |
| | 1773 | } |
| | 1774 | return .{ .group = .top, .assoc = .left }; |
| | 1775 | } |
| | 1776 | |
| | 1777 | pub fn precedenceFromNodeTag(tag: Node.Tag) PrecClass { |
| | 1778 | return switch (tag) { |
| | 1779 | inline else => |ct_tag| comptimePrecedenceFromNodeTag(ct_tag), |
| | 1780 | }; |
| | 1781 | } |
| | 1782 | |
| | 1783 | pub fn newPrecedenceBetween(left_tok: Node.Tag, right_tok: Node.Tag) ?PrecClass.Rel { |
| | 1784 | return precedenceFromNodeTag(left_tok).cmp(precedenceFromNodeTag(right_tok)); |
| | 1785 | } |
| | 1786 | |
| 1765 | fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index { | 1787 | fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index { |
| 1766 | var node = try p.parsePrefixExpr() orelse return null; | 1788 | var node = try p.parsePrefixExpr() orelse return null; |
| 1767 | | 1789 | |
| ... | @@ -1769,17 +1791,21 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 | ... | @@ -1769,17 +1791,21 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 |
| 1769 | | 1791 | |
| 1770 | while (true) { | 1792 | while (true) { |
| 1771 | const tok_tag = p.tokenTag(p.tok_i); | 1793 | const tok_tag = p.tokenTag(p.tok_i); |
| 1772 | const info = operTable[@intFromEnum(tok_tag)]; | 1794 | const info = operTable[@backingInt(tok_tag)]; |
| 1773 | | 1795 | |
| 1774 | const rel = info.prec.cmp(min_exc_prec) orelse b: { | 1796 | const prec_relation = if (!p.use_old_precedence) info.prec.cmp(min_exc_prec) else info.prec.v16_cmp(min_exc_prec); |
| | 1797 | const rel = prec_relation orelse b: { |
| | 1798 | // This issues warnings if the relation is null, which it never is in 0.16.0 |
| 1775 | const prev_op_tok_tag = p.tokenTag(prev_operator_token); | 1799 | const prev_op_tok_tag = p.tokenTag(prev_operator_token); |
| 1776 | const prev_op_info = operTable[@intFromEnum(prev_op_tok_tag)]; | 1800 | const prev_op_info = operTable[@backingInt(prev_op_tok_tag)]; |
| 1777 | const v16_rel = prev_op_info.prec.v16_cmp(info.prec); | 1801 | const v16_rel = prev_op_info.prec.v16_cmp(info.prec); |
| 1778 | try p.warnMsg(.{ | 1802 | try p.warnMsg(.{ |
| 1779 | .tag = .ambiguous_operator_precedence, | 1803 | .tag = .ambiguous_operator_precedence, |
| 1780 | .is_note = false, | 1804 | .is_note = false, |
| 1781 | .token = p.tok_i, | 1805 | .token = p.tok_i, |
| 1782 | .extra = .{ .offset = p.tok_i - prev_operator_token }, | 1806 | .extra = .{ |
| | 1807 | .offset = p.tok_i - prev_operator_token, |
| | 1808 | }, |
| 1783 | }); | 1809 | }); |
| 1784 | try p.warnMsg(.{ | 1810 | try p.warnMsg(.{ |
| 1785 | .tag = .previous_ambiguous_operator, | 1811 | .tag = .previous_ambiguous_operator, |
| ... | @@ -1791,14 +1817,18 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 | ... | @@ -1791,14 +1817,18 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 |
| 1791 | .tag = .hint_operator_precedence_left, | 1817 | .tag = .hint_operator_precedence_left, |
| 1792 | .is_note = true, | 1818 | .is_note = true, |
| 1793 | .token = p.tok_i, | 1819 | .token = p.tok_i, |
| 1794 | .extra = .{ .offset = p.tok_i - prev_operator_token }, | 1820 | .extra = .{ |
| | 1821 | .offset = p.tok_i - prev_operator_token, |
| | 1822 | }, |
| 1795 | }); | 1823 | }); |
| 1796 | } else { | 1824 | } else { |
| 1797 | try p.warnMsg(.{ | 1825 | try p.warnMsg(.{ |
| 1798 | .tag = .hint_operator_precedence_right, | 1826 | .tag = .hint_operator_precedence_right, |
| 1799 | .is_note = true, | 1827 | .is_note = true, |
| 1800 | .token = p.tok_i, | 1828 | .token = p.tok_i, |
| 1801 | .extra = .{ .offset = p.tok_i - prev_operator_token }, | 1829 | .extra = .{ |
| | 1830 | .offset = p.tok_i - prev_operator_token, |
| | 1831 | }, |
| 1802 | }); | 1832 | }); |
| 1803 | } | 1833 | } |
| 1804 | break :b .gt; | 1834 | break :b .gt; |
| ... | @@ -1812,12 +1842,15 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 | ... | @@ -1812,12 +1842,15 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 |
| 1812 | //Special cased check to maintain the old more helpful error for chained comparisons. | 1842 | //Special cased check to maintain the old more helpful error for chained comparisons. |
| 1813 | if (info.prec.group == .comparison) { | 1843 | if (info.prec.group == .comparison) { |
| 1814 | try p.warn(.chained_comparison_operators); | 1844 | try p.warn(.chained_comparison_operators); |
| 1815 | } else { | 1845 | // In 0.16.0 the only reptition prohibited was comparisons which we checked above |
| | 1846 | } else if (!p.use_old_precedence) { |
| 1816 | try p.warnMsg(.{ | 1847 | try p.warnMsg(.{ |
| 1817 | .tag = .illegal_chained_operators, | 1848 | .tag = .illegal_chained_operators, |
| 1818 | .is_note = false, | 1849 | .is_note = false, |
| 1819 | .token = p.tok_i, | 1850 | .token = p.tok_i, |
| 1820 | .extra = .{ .offset = p.tok_i - prev_operator_token }, | 1851 | .extra = .{ |
| | 1852 | .offset = p.tok_i - prev_operator_token, |
| | 1853 | }, |
| 1821 | }); | 1854 | }); |
| 1822 | try p.warnMsg(.{ | 1855 | try p.warnMsg(.{ |
| 1823 | .tag = .previous_ambiguous_operator, | 1856 | .tag = .previous_ambiguous_operator, |
| ... | @@ -1828,7 +1861,9 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 | ... | @@ -1828,7 +1861,9 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 |
| 1828 | .tag = .hint_operator_precedence_left, | 1861 | .tag = .hint_operator_precedence_left, |
| 1829 | .is_note = true, | 1862 | .is_note = true, |
| 1830 | .token = p.tok_i, | 1863 | .token = p.tok_i, |
| 1831 | .extra = .{ .offset = p.tok_i - prev_operator_token }, | 1864 | .extra = .{ |
| | 1865 | .offset = p.tok_i - prev_operator_token, |
| | 1866 | }, |
| 1832 | }); | 1867 | }); |
| 1833 | } | 1868 | } |
| 1834 | } | 1869 | } |