Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
26a52b3
more tweaks in InputForm
mmatera Jan 19, 2026
e67e06f
improve OptionValues InputForm. Adding documentation
mmatera Jan 19, 2026
f843756
improve Definition
mmatera Jan 19, 2026
14ddd30
Fix parenthesized condition in inputform.py
mmatera Jan 19, 2026
d7cdc45
Use new implementation of OutputForm
mmatera Jan 19, 2026
a5a2f09
more explicit logic for parenthesize
mmatera Jan 19, 2026
13c71b9
more explicit parenthesize
mmatera Jan 19, 2026
0f84406
merge
mmatera Jan 19, 2026
dff8acd
group in
mmatera Jan 19, 2026
461f552
group in
mmatera Jan 19, 2026
8e6db2f
Merge branch 'more_on_inputform' into rebase_1d_OutputForm
mmatera Jan 19, 2026
54be619
improve associativity
mmatera Jan 19, 2026
e670635
merge
mmatera Jan 19, 2026
34d5c01
Merge remote-tracking branch 'origin/rebase_1d_OutputForm' into rebas…
mmatera Jan 19, 2026
616c143
Update mathics/format/form/util.py
mmatera Jan 19, 2026
fd095d9
black
mmatera Jan 19, 2026
d9b7184
Merge branch 'more_on_inputform' into rebase_1d_OutputForm
mmatera Jan 19, 2026
f6395c8
Apply suggestions from code review
mmatera Jan 19, 2026
018b5e2
Merge branch 'more_on_inputform' into rebase_1d_OutputForm
mmatera Jan 19, 2026
3a74c9e
fix alternatives
mmatera Jan 19, 2026
dd5ad9e
Merge remote-tracking branch 'origin/master' into rebase_1d_OutputForm
mmatera Jan 20, 2026
bc8826b
move MakeBoxes rules to their right place
mmatera Jan 20, 2026
b591419
fix Optional
mmatera Jan 20, 2026
e597a04
handle `Optional` in OutputForm. Fix PrecedenceForm.
mmatera Jan 20, 2026
e24eac4
Merge branch 'rebase_1d_OutputForm' into move_makeboxes_rules_to_thei…
mmatera Jan 20, 2026
de96e38
add more tests for format_test.yaml
mmatera Jan 20, 2026
45c4445
Merge remote-tracking branch 'origin/move_makeboxes_rules_to_their_sy…
mmatera Jan 20, 2026
95b08a2
merge
mmatera Jan 20, 2026
cc4925d
Merge remote-tracking branch 'origin/master' into move_makeboxes_rule…
mmatera Jan 20, 2026
a718404
makeboxes_overhault
mmatera Jan 21, 2026
a733349
add FormBox
mmatera Jan 21, 2026
2eb1105
Merge branch 'formbox' into makeboxes_overhault
mmatera Jan 21, 2026
a97fa9b
removing trailing code
mmatera Jan 21, 2026
76fac71
interpretationbox tweaks
mmatera Jan 21, 2026
51bb3c9
missing import. Input and FullForm escape quotes in strings
mmatera Jan 21, 2026
02e7c12
Update layout.py
mmatera Jan 23, 2026
ba922a1
Makeboxes overhault (#1642)
mmatera Jan 24, 2026
7c3b14f
Merge branch 'master' into move_makeboxes_rules_to_their_symbols
mmatera Jan 25, 2026
35f9dc4
Merge branch 'master' into formbox
mmatera Jan 25, 2026
5e9213f
format optional
mmatera Jan 25, 2026
55d5c1e
Merge branch 'Format_Optional' into move_makeboxes_rules_to_their_sym…
mmatera Jan 25, 2026
322be25
Merge remote-tracking branch 'origin/master' into makeboxes_overhault
mmatera Jan 25, 2026
d85b179
new_formbox
mmatera Jan 25, 2026
1004bc9
add FormBox
mmatera Jan 25, 2026
99bb5b6
Merge branch 'formbox' into makeboxes_overhault
mmatera Jan 25, 2026
ab21698
Merge branch 'move_makeboxes_rules_to_their_symbols' into new_formbox
mmatera Jan 25, 2026
a42e744
Merge branch 'master' into new_formbox
mmatera Jan 25, 2026
2e7083b
Merge branch 'new_formbox' into makeboxes_overhault
mmatera Jan 25, 2026
9e8fc07
merge
mmatera Jan 25, 2026
1c6c63c
Merge remote-tracking branch 'origin/master' into makeboxes_overhault
mmatera Jan 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 36 additions & 57 deletions mathics/builtin/forms/print.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@
below are the functions that appear in '$PrintForms' at startup.
"""

from mathics.builtin.box.layout import InterpretationBox, StyleBox, TagBox
from mathics.builtin.box.layout import InterpretationBox, PaneBox, StyleBox
from mathics.builtin.forms.base import FormBaseClass
from mathics.core.atoms import String
from mathics.core.element import BaseElement
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.symbols import SymbolFalse, SymbolFullForm, SymbolTrue
from mathics.core.symbols import SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import SymbolInputForm, SymbolOutputForm
from mathics.format.box import (
eval_makeboxes_fullform,
eval_makeboxes_outputform,
eval_mathmlform,
eval_texform,
)
from mathics.format.form import render_input_form
from mathics.format.box.makeboxes import is_print_form_callback
from mathics.format.form import render_input_form, render_output_form

sort_order = "mathics.builtin.forms.general-purpose-forms"

Expand Down Expand Up @@ -52,19 +49,6 @@ class FullForm(FormBaseClass):
in_printforms = False
summary_text = "format expression in underlying M-Expression representation"

def eval_makeboxes(self, expr, fmt, evaluation):
"""MakeBoxes[FullForm[expr_], fmt_]"""
fullform_box = eval_makeboxes_fullform(expr, evaluation)
style_box = StyleBox(
fullform_box,
**{
"System`ShowSpecialCharacters": SymbolFalse,
"System`ShowStringCharacters": SymbolTrue,
"System`NumberMarks": SymbolTrue,
},
)
return TagBox(style_box, SymbolFullForm)


class InputForm(FormBaseClass):
r"""
Expand Down Expand Up @@ -116,26 +100,6 @@ class InputForm(FormBaseClass):
in_printforms = True
summary_text = "format expression suitable for Mathics3 input"

# TODO: eventually, remove OutputForm in the second argument.
def eval_makeboxes(self, expr, evaluation):
"""MakeBoxes[InputForm[expr_], StandardForm|TraditionalForm]"""

inputform = String(render_input_form(expr, evaluation))
inputform = StyleBox(
inputform,
**{
"System`ShowSpecialCharacters": SymbolFalse,
"System`ShowStringCharacters": SymbolTrue,
"System`NumberMarks": SymbolTrue,
},
)
expr = Expression(SymbolInputForm, expr)
return InterpretationBox(
inputform,
expr,
**{"System`Editable": SymbolTrue, "System`AutoDelete": SymbolTrue},
)


class MathMLForm(FormBaseClass):
"""
Expand Down Expand Up @@ -169,10 +133,6 @@ class MathMLForm(FormBaseClass):

summary_text = "format expression as MathML commands"

def eval_mathml(self, expr, evaluation) -> Expression:
"MakeBoxes[MathMLForm[expr_], StandardForm|TraditionalForm]"
return eval_mathmlform(expr, evaluation)


class OutputForm(FormBaseClass):
"""
Expand Down Expand Up @@ -202,13 +162,6 @@ class OutputForm(FormBaseClass):
formats = {"OutputForm[s_String]": "s"}
summary_text = "format expression in plain text"

def eval_makeboxes(self, expr, form, evaluation):
"""MakeBoxes[OutputForm[expr_], form_]"""
pane = eval_makeboxes_outputform(expr, evaluation, form)
return InterpretationBox(
pane, Expression(SymbolOutputForm, expr), **{"System`Editable": SymbolFalse}
)


class StandardForm(FormBaseClass):
"""
Expand Down Expand Up @@ -276,8 +229,34 @@ class TeXForm(FormBaseClass):
in_printforms = True
summary_text = "format expression as LaTeX commands"

def eval_tex(self, expr, evaluation) -> Expression:
"MakeBoxes[TeXForm[expr_], StandardForm|TraditionalForm]"
# TeXForm by default uses `TraditionalForm`

return eval_texform(expr, evaluation)
@is_print_form_callback("System`InputForm")
def eval_makeboxes_inputform(expr: BaseElement, evaluation: Evaluation):
"""MakeBoxes[InputForm[expr_], StandardForm|TraditionalForm]"""
inputform = String(render_input_form(expr, evaluation))
inputform = StyleBox(
inputform,
**{
"System`ShowStringCharacters": SymbolTrue,
"System`NumberMarks": SymbolTrue,
},
)
expr = Expression(SymbolInputForm, expr)
return InterpretationBox(
inputform,
expr,
**{"System`Editable": SymbolTrue, "System`AutoDelete": SymbolTrue},
)


@is_print_form_callback("System`OutputForm")
def eval_makeboxes_outputform(expr: BaseElement, evaluation: Evaluation, **kwargs):
"""
Build a 2D representation of the expression using only keyboard characters.
"""

text_outputform = str(render_output_form(expr, evaluation, **kwargs))
pane = PaneBox(String('"' + text_outputform + '"'))
return InterpretationBox(
pane, Expression(SymbolOutputForm, expr), **{"System`Editable": SymbolFalse}
)
10 changes: 1 addition & 9 deletions mathics/builtin/list/constructing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from itertools import permutations
from typing import Optional, Tuple

from mathics.builtin.box.layout import RowBox
from mathics.core.atoms import ByteArray, Integer, Integer1, is_integer_rational_or_real
from mathics.core.attributes import A_HOLD_FIRST, A_LISTABLE, A_LOCKED, A_PROTECTED
from mathics.core.builtin import BasePattern, Builtin, IterationFunction
Expand All @@ -24,7 +23,7 @@
from mathics.core.list import ListExpression
from mathics.core.symbols import Atom, Symbol
from mathics.core.systemsymbols import SymbolNormal, SymbolTuples
from mathics.eval.lists import get_tuples, list_boxes
from mathics.eval.lists import get_tuples


class Array(Builtin):
Expand Down Expand Up @@ -165,13 +164,6 @@ def eval(self, elements, evaluation: Evaluation):
elements_part_of_elements__ = elements.get_sequence()
return ListExpression(*elements_part_of_elements__)

def eval_makeboxes(self, items, f, evaluation):
"""MakeBoxes[{items___},
(f:StandardForm|TraditionalForm)]"""

items = items.get_sequence()
return RowBox(*list_boxes(items, f, evaluation, "{", "}"))


class Normal(Builtin):
"""
Expand Down
10 changes: 3 additions & 7 deletions mathics/builtin/makeboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
Low-level Format definitions
"""


from mathics.core.attributes import A_HOLD_ALL_COMPLETE, A_READ_PROTECTED
from mathics.core.builtin import Builtin, Predefined
from mathics.format.box import eval_generic_makeboxes, format_element
from mathics.format.box import format_element

# TODO: Differently from the current implementation, MakeBoxes should only
# accept as its format field the symbols in `$BoxForms`. This is something to
Expand Down Expand Up @@ -85,16 +84,12 @@ class MakeBoxes(Builtin):
"MakeBoxes[expr_]": "MakeBoxes[expr, StandardForm]",
# The following rule is temporal.
"MakeBoxes[expr_, form:(TeXForm|MathMLForm)]": "MakeBoxes[form[expr], StandardForm]",
(
"MakeBoxes[(form:StandardForm|TraditionalForm)"
"[expr_], StandardForm|TraditionalForm]"
): ("MakeBoxes[expr, form]"),
}
summary_text = "settable low-level translator from expression to display boxes"

def eval_general(self, expr, f, evaluation):
"""MakeBoxes[expr_, f:TraditionalForm|StandardForm]"""
return eval_generic_makeboxes(expr, f, evaluation)
return format_element(expr, evaluation, f)


class ToBoxes(Builtin):
Expand Down Expand Up @@ -126,5 +121,6 @@ def eval(self, expr, form, evaluation):
form_name = form.get_name()
if form_name is None:
evaluation.message("ToBoxes", "boxfmt", form)

boxes = format_element(expr, evaluation, form)
return boxes
9 changes: 4 additions & 5 deletions mathics/core/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ def contextify_form_name(f):
"""Handle adding 'System`' to a form name, unless it's ""
(meaning the rule applies to all forms).
"""
return "" if f == "" else ensure_context(f)
return f if f in ("", "_MakeBoxes") else ensure_context(f)

if isinstance(pattern, tuple):
forms, pattern = pattern
Expand Down Expand Up @@ -383,6 +383,9 @@ def contextify_form_name(f):
formatvalues[form].append(
Rule(pattern, parse_builtin_rule(replace), system=True)
)

formatvalues.setdefault("_MakeBoxes", []).extend(box_rules)

for form, formatrules in formatvalues.items():
formatrules.sort(key=lambda x: x.pattern_precedence)

Expand Down Expand Up @@ -434,10 +437,6 @@ def contextify_form_name(f):
else:
definitions.builtin[name] = definition

makeboxes_def = definitions.builtin["System`MakeBoxes"]
for rule in box_rules:
makeboxes_def.add_rule(rule)

# This method is used to produce generic argument mismatch errors
# (tags: "argx", "argr", "argrx", "argt", or "argtu") for builtin
# functions that define this as an eval method. e.g. For example
Expand Down
5 changes: 1 addition & 4 deletions mathics/core/load_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,8 @@ def definition_contribute(definitions):
Load the Definition objects associated to all the builtins
on `Definitions`
"""
# let MakeBoxes contribute first
_builtins["System`MakeBoxes"].contribute(definitions)
for name, item in _builtins.items():
if name != "System`MakeBoxes":
item.contribute(definitions)
item.contribute(definitions)

from mathics.core.definitions import Definition
from mathics.core.expression import ensure_context
Expand Down
3 changes: 1 addition & 2 deletions mathics/doc/documentation/1-Manual.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -912,14 +912,13 @@ In a similar way, in the CLI, we can ask for TraditionalForm explicitly
= c

'MakeBoxes' for another form:

>> MakeBoxes[TeXForm[b], form_] = "d";
>> b // TeXForm
= ...

You can cause a much bigger mess by overriding 'MakeBoxes' than by sticking to 'Format', e.g. generate invalid XML:

>> MakeBoxes[MathMLForm[c], form_] = "<not closed";
>> MakeBoxes[MathMLForm[c], form_] := "<not closed";
>> c // MathMLForm //StandardForm
= <not closed

Expand Down
29 changes: 18 additions & 11 deletions mathics/eval/assignments/assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,19 +661,26 @@ def eval_assign_makeboxes(
True if the assignment was successful.

"""
# FIXME: the below is a big hack.
# Currently MakeBoxes boxing is implemented as a bunch of rules.
# See mathics.core.builtin contribute().
# I think we want to change this so it works like normal SetDelayed
# That is:
# MakeBoxes[CubeRoot, StandardForm] := RadicalBox[3, StandardForm]
# rather than:
# MakeBoxes[CubeRoot, StandardForm] -> RadicalBox[3, StandardForm]
if not lhs.has_form("MakeBoxes", 2):
evaluation.message("MakeBoxes", "argrx", Integer(len(lhs.elements)))
raise AssignmentException(lhs, None)
target, form = lhs.elements
# Check second argument

makeboxes_rule = Rule(lhs, rhs, system=False)
tags = [] if tags is None else tags
if upset:
tags = tags + [target.get_lookup_name()]
else:
if not tags:
tags = ["System`MakeBoxes"]

definitions = evaluation.definitions
definitions.add_rule("System`MakeBoxes", makeboxes_rule, "downvalues")
# makeboxes_defs = evaluation.definitions.builtin["System`MakeBoxes"]
# makeboxes_defs.add_rule(makeboxes_rule)
for tag in tags:
if is_protected(tag, definitions):
evaluation.message(self.get_name(), "wrsym", Symbol(tag))
return False
definitions.add_format(tag, makeboxes_rule, "_MakeBoxes")
return True


Expand Down
3 changes: 2 additions & 1 deletion mathics/eval/lists.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from mathics.builtin.box.layout import RowBox
from mathics.core.atoms import String
from mathics.core.convert.expression import to_expression
from mathics.core.exceptions import PartDepthError, PartRangeError
Expand Down Expand Up @@ -61,6 +60,8 @@ def get_tuples(items):


def list_boxes(items, f, evaluation, open=None, close=None):
from mathics.builtin.box.layout import RowBox

result = [
Expression(SymbolMakeBoxes, item, f).evaluate(evaluation) for item in items
]
Expand Down
4 changes: 0 additions & 4 deletions mathics/format/box/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
from mathics.format.box.makeboxes import (
_boxed_string,
eval_generic_makeboxes,
eval_makeboxes,
eval_makeboxes_fullform,
eval_makeboxes_outputform,
format_element,
to_boxes,
)
Expand Down Expand Up @@ -36,9 +34,7 @@
"eval_baseform",
"eval_generic_makeboxes",
"eval_infix",
"eval_makeboxes",
"eval_makeboxes_fullform",
"eval_makeboxes_outputform",
"eval_mathmlform",
"eval_postprefix",
"eval_tableform",
Expand Down
Loading
Loading