diff --git a/mathics/core/pattern/base.py b/mathics/core/pattern/base.py index 16b6f96c4..1a8618113 100644 --- a/mathics/core/pattern/base.py +++ b/mathics/core/pattern/base.py @@ -480,7 +480,14 @@ def __init__( def _build_pattern_sort_key(self) -> tuple: if self.isliteral: - return (BASIC_LITERAL_EXPRESSION_PATTERN_SORT_KEY, self.expr.element_order) + # Keep the shape of BASIC_ATOM_PATTERN_SORT_KEY (magic, int, ...): + # atoms share the magic number, so the second slot must be an int + # here too, or sorting an Orderless pattern mixing both fails. + return ( + BASIC_LITERAL_EXPRESSION_PATTERN_SORT_KEY, + 1, + self.expr.element_order, + ) return ( BASIC_EXPRESSION_PATTERN_SORT_KEY, self.head.pattern_precedence, diff --git a/test/builtin/test_patterns.py b/test/builtin/test_patterns.py index 6f1ccbe28..e93a2dc4d 100644 --- a/test/builtin/test_patterns.py +++ b/test/builtin/test_patterns.py @@ -168,6 +168,9 @@ def test_dispatch(str_expr, msgs, str_expected, fail_msg): ("f[10]", None, "100", None), ("f[10, Power -> 3]", None, "1000", None), ("Clear[f]", None, None, None), + # Orderless literal pattern mixing an atom and an expression + ("f[2 x[3]] = 1; f[2 x[3]]", None, "1", None), + ("Clear[f]", None, None, None), ], ) def test_pattern(str_expr, msgs, str_expected, fail_msg): diff --git a/test/builtin/test_testing_expressions.py b/test/builtin/test_testing_expressions.py index 7c25af60f..d890c5d16 100644 --- a/test/builtin/test_testing_expressions.py +++ b/test/builtin/test_testing_expressions.py @@ -182,6 +182,10 @@ def test_numerical_properties(str_expr, msgs, str_expected, fail_msg): ("MatchQ[1, a_.*b_.]", None, "True", None), ("MatchQ[x, a_.*b_.]", None, "True", None), ("MatchQ[2*x, a_.*b_.]", None, "True", None), + # Orderless literal patterns mixing an atom and an expression + ("MatchQ[2 x[3], 2 x[3]]", None, "True", None), + ("MatchQ[x[3] + 2, 2 + x[3]]", None, "True", None), + ("MatchQ[2 x[3], 3 x[3]]", None, "False", None), ], ) def test_matchq(str_expr, msgs, str_expected, fail_msg):