From dbced9628689dd2d892d46d5adc08a7a177239ce Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Wed, 2 Sep 2026 08:20:34 -0300 Subject: [PATCH 1/2] add TagUnset buitlin --- SYMBOLS_MANIFEST.txt | 1 + mathics/builtin/assignments/clear.py | 78 ++++++++++++++++++++++++---- mathics/core/systemsymbols.py | 11 ++++ 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/SYMBOLS_MANIFEST.txt b/SYMBOLS_MANIFEST.txt index 87a2cbf3e..3497ec991 100644 --- a/SYMBOLS_MANIFEST.txt +++ b/SYMBOLS_MANIFEST.txt @@ -1218,6 +1218,7 @@ System`SyntaxQ System`Table System`TableForm System`TagBox +System`TagUnset System`TagSet System`TagSetDelayed System`Take diff --git a/mathics/builtin/assignments/clear.py b/mathics/builtin/assignments/clear.py index b31bbae06..1ce89f089 100644 --- a/mathics/builtin/assignments/clear.py +++ b/mathics/builtin/assignments/clear.py @@ -19,6 +19,7 @@ from mathics.core.expression import Expression from mathics.core.symbols import Atom, Symbol, SymbolNull, symbol_set from mathics.core.systemsymbols import ( + SYSTEM_SYMBOL_VALUES, SymbolContext, SymbolContextPath, SymbolDownValues, @@ -285,12 +286,71 @@ def eval(self, expr, evaluation): return SymbolNull -SYSTEM_SYMBOL_VALUES = symbol_set( - SymbolDownValues, - SymbolMessages, - SymbolNValues, - SymbolOptions, - SymbolOwnValues, - SymbolSubValues, - SymbolUpValues, -) +class TagUnset(PostfixOperator): + """ + + :WMA link: + https://reference.wolfram.com/language/ref/TagUnset.html + +
+
'TagUnset'[$f$, $patt$] +
'f/: $patt$=.' +
removes any value belonging to the patter $patt$ from $f$. +
+ + + + Let's consider we define an UpValue for a symbol g: + >> Sin[g[x_]]^:=Sing[x]; + in a way that + >> Sin[g[3]] + = Sing[3] + + TagUset allows to remove the rule: + >> g/: Sin[g[x_]]=. + >> Sin[g[3]] + = Sin[g[3]] + """ + + attributes = A_HOLD_ALL | A_PROTECTED + + messages = { + "norep": "Assignment on `2` for `1` not found.", + "sym": "Argument `1` at position 1 is expected to be a symbol.", + "tag": "Rule for `1` of `2` can only be attached to `3`.", + } + summary_text = "unset a value of the LHS, associated to a symbol." + + def eval_general(self, tag, expr, evaluation): + "TagUnset[tag_, expr_]" + + if not isinstance(tag, Symbol): + evaluation.message("TagSet", "sym", tag) + return SymbolNull + tag_name = tag.get_name() + head = expr.get_head() + if head in SYSTEM_SYMBOL_VALUES: + if len(expr.elements) != 1: + evaluation.message_args(expr.get_head_name(), len(expr.elements), 1) + return SymbolFailed + target_symbol = expr.elements[0] + if not target_symbol.sameQ(tag): + evaluation.message("TagUnset", "tag", target_symbol, expr, tag) + return SymbolFailed + symbol = target_symbol.get_name() + if not symbol: + evaluation.message(expr.get_head_name(), "fnsym", expr) + return SymbolFailed + if head is SymbolOptions: + empty = {} + else: + empty = [] + evaluation.definitions.set_values(symbol, expr.get_head_name(), empty) + return SymbolNull + + if not tag_name: + return SymbolNull + if not evaluation.definitions.unset(tag_name, expr): + evaluation.message("TagUnset", "norep", expr, Symbol(name)) + return SymbolFailed + return SymbolNull diff --git a/mathics/core/systemsymbols.py b/mathics/core/systemsymbols.py index 234bf694d..87658edfc 100644 --- a/mathics/core/systemsymbols.py +++ b/mathics/core/systemsymbols.py @@ -447,3 +447,14 @@ SymbolRepeated, SymbolRepeatedNull, ) + + +SYSTEM_SYMBOL_VALUES = symbol_set( + SymbolDownValues, + SymbolMessages, + SymbolNValues, + SymbolOptions, + SymbolOwnValues, + SymbolSubValues, + SymbolUpValues, +) From 603beacc603350c65625bd2a59dfd8fbbdd7f32a Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Wed, 2 Sep 2026 08:32:05 -0300 Subject: [PATCH 2/2] ruff --- admin-tools/check_benchmarks.py | 1 - admin-tools/normalize_benchmarks.py | 4 +++- mathics/builtin/assignments/clear.py | 10 ++-------- mathics/eval/options/values.py | 2 +- test/builtin/assumptions/test_assumptions.py | 2 +- test/core/convert/test_sympy.py | 11 +---------- test/timings/test_regressions.py | 3 --- 7 files changed, 8 insertions(+), 25 deletions(-) diff --git a/admin-tools/check_benchmarks.py b/admin-tools/check_benchmarks.py index ee35b6b06..6145b84be 100644 --- a/admin-tools/check_benchmarks.py +++ b/admin-tools/check_benchmarks.py @@ -20,7 +20,6 @@ import argparse import json -import os import sys from pathlib import Path diff --git a/admin-tools/normalize_benchmarks.py b/admin-tools/normalize_benchmarks.py index 6d7b809a3..a6b18c21e 100644 --- a/admin-tools/normalize_benchmarks.py +++ b/admin-tools/normalize_benchmarks.py @@ -25,7 +25,9 @@ def normalize_benchmarks(target_file): break if ref_bench is None: - print(f"⚠️ Benchmark for the reference task '{REFERENCE_NAME} not found'. Exit.") + print( + f"⚠️ Benchmark for the reference task '{NORMALIZATION_TASK_KEY} not found'. Exit." + ) sys.exit(1) # Extract the reference value diff --git a/mathics/builtin/assignments/clear.py b/mathics/builtin/assignments/clear.py index 1ce89f089..329fae2c9 100644 --- a/mathics/builtin/assignments/clear.py +++ b/mathics/builtin/assignments/clear.py @@ -17,19 +17,13 @@ ) from mathics.core.builtin import Builtin, PostfixOperator from mathics.core.expression import Expression -from mathics.core.symbols import Atom, Symbol, SymbolNull, symbol_set +from mathics.core.symbols import Atom, Symbol, SymbolNull from mathics.core.systemsymbols import ( SYSTEM_SYMBOL_VALUES, SymbolContext, SymbolContextPath, - SymbolDownValues, SymbolFailed, - SymbolMessages, - SymbolNValues, SymbolOptions, - SymbolOwnValues, - SymbolSubValues, - SymbolUpValues, ) @@ -351,6 +345,6 @@ def eval_general(self, tag, expr, evaluation): if not tag_name: return SymbolNull if not evaluation.definitions.unset(tag_name, expr): - evaluation.message("TagUnset", "norep", expr, Symbol(name)) + evaluation.message("TagUnset", "norep", expr, tag) return SymbolFailed return SymbolNull diff --git a/mathics/eval/options/values.py b/mathics/eval/options/values.py index c59c97756..220361bff 100644 --- a/mathics/eval/options/values.py +++ b/mathics/eval/options/values.py @@ -1,5 +1,5 @@ from mathics.core.parser import parse_builtin_rule -from mathics.core.symbols import SymbolList, strip_context +from mathics.core.symbols import strip_context def filter_non_default_values(builtin): diff --git a/test/builtin/assumptions/test_assumptions.py b/test/builtin/assumptions/test_assumptions.py index e331af528..bde383848 100644 --- a/test/builtin/assumptions/test_assumptions.py +++ b/test/builtin/assumptions/test_assumptions.py @@ -152,7 +152,7 @@ def test_assumptions_integrate(str_expr, str_expected, message): LIST_TEST_ASSUMPTIONS_INTEGRATE_FAILING, ) @pytest.mark.xfail(reason="the Assumptions with Integrate is not fully working") -def test_assumptions_integrate(str_expr, str_expected, message): +def test_assumptions_integrate2(str_expr, str_expected, message): check_evaluation(str_expr, str_expected) diff --git a/test/core/convert/test_sympy.py b/test/core/convert/test_sympy.py index ce1117838..35df0c7c2 100644 --- a/test/core/convert/test_sympy.py +++ b/test/core/convert/test_sympy.py @@ -39,16 +39,7 @@ Symbol_F = Symbol("Global`F") Symbol_G = Symbol("Global`G") -from mathics.core.expression import Expression -from mathics.core.expression_predefined import MATHICS3_COMPLEX_INFINITY -from mathics.core.symbols import ( - Symbol, - SymbolNull, - SymbolPlus, - SymbolPower, - SymbolTimes, -) -from mathics.core.systemsymbols import SymbolE, SymbolExp, SymbolI, SymbolPi, SymbolSin +from mathics.core.symbols import Symbol Symbol_a = Symbol("Global`a") Symbol_b = Symbol("Global`b") diff --git a/test/timings/test_regressions.py b/test/timings/test_regressions.py index 096000980..968e84e66 100644 --- a/test/timings/test_regressions.py +++ b/test/timings/test_regressions.py @@ -152,9 +152,6 @@ param_ids = [name for name, _, _, _ in BENCHMARK_TASKS] -import pytest - - @pytest.mark.skipif( not os.environ.get("BENCHMARKS", 0), reason="benchmarks not required" )