Skip to content

Commit a35983e

Browse files
committed
formatting OutputForm
outputform and fullform following the WMA formatting steps
1 parent b6eac71 commit a35983e

File tree

9 files changed

+900
-11
lines changed

9 files changed

+900
-11
lines changed

mathics/builtin/box/layout.py

+27
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,33 @@ def eval_display(boxexpr, evaluation):
188188
return boxexpr.elements[0]
189189

190190

191+
class PaneBox(BoxExpression):
192+
"""
193+
<url>
194+
:WMA link:
195+
https://reference.wolfram.com/language/ref/InterpretationBox.html</url>
196+
197+
<dl>
198+
<dt>'PaneBox[expr]'
199+
<dd> is a low-level box construct, used in OutputForm.
200+
</dl>
201+
202+
"""
203+
204+
attributes = A_HOLD_ALL_COMPLETE | A_PROTECTED | A_READ_PROTECTED
205+
summary_text = "box associated to panel"
206+
207+
def apply_display_form(boxexpr, form, evaluation, expression):
208+
"""ToExpression[boxexpr_PaneBox, form_]"""
209+
return Expression(expression.head, boxexpr.elements[0], form).evaluate(
210+
evaluation
211+
)
212+
213+
def apply_display(boxexpr, evaluation):
214+
"""DisplayForm[boxexpr_PaneBox]"""
215+
return boxexpr.elements[0]
216+
217+
191218
class RowBox(BoxExpression):
192219
"""
193220
<url>

mathics/builtin/forms/output.py

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
StringLParen,
3838
StringRParen,
3939
eval_baseform,
40+
eval_makeboxes_outputform,
4041
eval_mathmlform,
4142
eval_tableform,
4243
eval_texform,
@@ -490,8 +491,13 @@ class OutputForm(FormBaseClass):
490491
= -Graphics-
491492
"""
492493

494+
formats = {"OutputForm[s_String]": "s"}
493495
summary_text = "plain-text output format"
494496

497+
def eval_makeboxes(self, expr, form, evaluation):
498+
"""MakeBoxes[OutputForm[expr_], form_]"""
499+
return eval_makeboxes_outputform(expr, evaluation, form)
500+
495501

496502
class PythonForm(FormBaseClass):
497503
"""

mathics/core/atoms.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1016,10 +1016,13 @@ def __str__(self) -> str:
10161016
return '"%s"' % self.value
10171017

10181018
def atom_to_boxes(self, f, evaluation):
1019+
return self.make_boxes(f.get_name())
1020+
1021+
def make_boxes(self, f):
10191022
from mathics.eval.makeboxes import _boxed_string
10201023

10211024
inner = str(self.value)
1022-
if f in SYSTEM_SYMBOLS_INPUT_OR_FULL_FORM:
1025+
if f in ("System`InputForm", "System`FullForm"):
10231026
inner = '"' + inner.replace("\\", "\\\\") + '"'
10241027
return _boxed_string(inner, **{"System`ShowStringCharacters": SymbolTrue})
10251028
return String('"' + inner + '"')

mathics/eval/makeboxes/__init__.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
_boxed_string,
88
eval_generic_makeboxes,
99
eval_makeboxes,
10+
eval_makeboxes_outputform,
1011
format_element,
1112
int_to_string_shorter_repr,
1213
to_boxes,
@@ -18,19 +19,25 @@
1819
eval_tableform,
1920
eval_texform,
2021
)
21-
from mathics.eval.makeboxes.precedence import builtins_precedence, parenthesize
22+
from mathics.eval.makeboxes.precedence import (
23+
builtins_precedence,
24+
compare_precedence,
25+
parenthesize,
26+
)
2227

2328
__all__ = [
2429
"NumberForm_to_String",
2530
"StringLParen",
2631
"StringRParen",
2732
"_boxed_string",
2833
"builtins_precedence",
34+
"compare_precedence",
2935
"do_format",
3036
"eval_baseform",
3137
"eval_generic_makeboxes",
3238
"eval_infix",
3339
"eval_makeboxes",
40+
"eval_makeboxes_outputform",
3441
"eval_mathmlform",
3542
"eval_postprefix",
3643
"eval_tableform",

mathics/eval/makeboxes/makeboxes.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from mathics.core.evaluation import Evaluation
1414
from mathics.core.expression import Expression
1515
from mathics.core.symbols import Atom, Symbol, SymbolFullForm, SymbolMakeBoxes
16-
from mathics.core.systemsymbols import SymbolStandardForm
16+
from mathics.core.systemsymbols import SymbolOutputForm, SymbolStandardForm
1717
from mathics.eval.makeboxes.formatvalues import do_format
1818
from mathics.eval.makeboxes.precedence import parenthesize
1919

@@ -126,8 +126,21 @@ def int_to_string_shorter_repr(value: int, form: Symbol, max_digits=640):
126126
return String(value_str)
127127

128128

129+
def eval_makeboxes_outputform(expr, evaluation, form):
130+
"""
131+
Build a 2D text representation of the expression.
132+
"""
133+
from mathics.builtin.box.layout import InterpretationBox, PaneBox
134+
from mathics.format.outputform import expression_to_outputform_text
135+
136+
text_outputform = str(expression_to_outputform_text(expr, evaluation, form))
137+
elem1 = PaneBox(String(text_outputform))
138+
elem2 = Expression(SymbolOutputForm, expr)
139+
return InterpretationBox(elem1, elem2)
140+
141+
129142
def eval_fullform_makeboxes(
130-
self, expr, evaluation: Evaluation, form=SymbolStandardForm
143+
expr, evaluation: Evaluation, form=SymbolStandardForm
131144
) -> Optional[BaseElement]:
132145
"""
133146
This function takes the definitions provided by the evaluation
@@ -220,9 +233,27 @@ def format_element(
220233
Applies formats associated to the expression, and then calls Makeboxes
221234
"""
222235
evaluation.is_boxing = True
236+
while element.get_head() is form:
237+
element = element.elements[0]
238+
239+
if element.has_form("FullForm", 1):
240+
return eval_fullform_makeboxes(element.elements[0], evaluation)
241+
242+
# In order to work like in WMA, `format_element`
243+
# should evaluate `MakeBoxes[element//form, StandardForm]`
244+
# Then, MakeBoxes[expr_, StandardForm], for any expr,
245+
# should apply Format[...] rules, and then
246+
# MakeBoxes[...] rules. These rules should be stored
247+
# as FormatValues[...]
248+
# As a first step in that direction, let's mimic this behaviour
249+
# just for the case of OutputForm:
250+
if element.has_form("OutputForm", 1):
251+
return eval_makeboxes_outputform(element.elements[0], evaluation, form)
252+
223253
expr = do_format(element, evaluation, form)
224254
if expr is None:
225255
return None
256+
226257
result = Expression(SymbolMakeBoxes, expr, form)
227258
result_box = result.evaluate(evaluation)
228259
if isinstance(result_box, String):

mathics/format/latex.py

+12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
from mathics.builtin.box.layout import (
2020
FractionBox,
2121
GridBox,
22+
InterpretationBox,
23+
PaneBox,
2224
RowBox,
2325
SqrtBox,
2426
StyleBox,
@@ -133,6 +135,16 @@ def render(format, string, in_text=False):
133135
add_conversion_fn(String, string)
134136

135137

138+
def interpretation_panebox(self, **options):
139+
return lookup_conversion_method(self.elements[0], "latex")(
140+
self.elements[0], **options
141+
)
142+
143+
144+
add_conversion_fn(InterpretationBox, interpretation_panebox)
145+
add_conversion_fn(PaneBox, interpretation_panebox)
146+
147+
136148
def fractionbox(self, **options) -> str:
137149
_options = self.box_options.copy()
138150
_options.update(options)

mathics/format/mathml.py

+12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from mathics.builtin.box.layout import (
1616
FractionBox,
1717
GridBox,
18+
InterpretationBox,
19+
PaneBox,
1820
RowBox,
1921
SqrtBox,
2022
StyleBox,
@@ -110,6 +112,16 @@ def render(format, string):
110112
add_conversion_fn(String, string)
111113

112114

115+
def interpretation_panebox(self, **options):
116+
return lookup_conversion_method(self.elements[0], "latex")(
117+
self.elements[0], **options
118+
)
119+
120+
121+
add_conversion_fn(InterpretationBox, interpretation_panebox)
122+
add_conversion_fn(PaneBox, interpretation_panebox)
123+
124+
113125
def fractionbox(self, **options) -> str:
114126
_options = self.box_options.copy()
115127
_options.update(options)

0 commit comments

Comments
 (0)