Skip to content

Commit b6eac71

Browse files
authored
Moving evaluation code from mathics.builtin.makeboxes to mathics.eval.makeboxes (#1309)
This goes in the same line as #1307. Essentially, moving code from mathics.builtin.makeboxes to `mathics.eval.makeboxes`, and reorganize the code inside `mathics.eval.makeboxes` as submodules.
1 parent 77f3f96 commit b6eac71

File tree

14 files changed

+940
-814
lines changed

14 files changed

+940
-814
lines changed

mathics/builtin/box/layout.py

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,29 @@
1010

1111
from mathics.builtin.box.expression import BoxExpression
1212
from mathics.builtin.options import options_to_rules
13-
from mathics.core.atoms import Atom, String
13+
from mathics.core.atoms import String
1414
from mathics.core.attributes import A_HOLD_ALL_COMPLETE, A_PROTECTED, A_READ_PROTECTED
1515
from mathics.core.builtin import Builtin
1616
from mathics.core.element import BoxElementMixin
1717
from mathics.core.evaluation import Evaluation
1818
from mathics.core.exceptions import BoxConstructError
1919
from mathics.core.expression import Expression
2020
from mathics.core.list import ListExpression
21-
from mathics.core.symbols import Symbol, SymbolFullForm
21+
from mathics.core.symbols import Symbol
2222
from mathics.core.systemsymbols import (
2323
SymbolFractionBox,
2424
SymbolRowBox,
2525
SymbolSqrtBox,
26-
SymbolStandardForm,
2726
SymbolSubscriptBox,
2827
SymbolSubsuperscriptBox,
2928
SymbolSuperscriptBox,
3029
)
31-
from mathics.eval.makeboxes import eval_makeboxes
30+
from mathics.eval.makeboxes import to_boxes
3231

3332
# Docs are not yet ready for prime time. Maybe after release 6.0.0.
3433
no_doc = True
3534

3635

37-
def to_boxes(x, evaluation: Evaluation, options={}) -> BoxElementMixin:
38-
"""
39-
This function takes the expression ``x``
40-
and tries to reduce it to a ``BoxElementMixin``
41-
expression using an evaluation object.
42-
"""
43-
if isinstance(x, BoxElementMixin):
44-
return x
45-
if isinstance(x, Atom):
46-
x = x.atom_to_boxes(SymbolStandardForm, evaluation)
47-
return to_boxes(x, evaluation, options)
48-
if isinstance(x, Expression):
49-
if x.has_form("MakeBoxes", None):
50-
x_boxed = x.evaluate(evaluation)
51-
else:
52-
x_boxed = eval_makeboxes(x, evaluation)
53-
if isinstance(x_boxed, BoxElementMixin):
54-
return x_boxed
55-
if isinstance(x_boxed, Atom):
56-
return to_boxes(x_boxed, evaluation, options)
57-
raise eval_makeboxes(Expression(SymbolFullForm, x), evaluation)
58-
59-
6036
class BoxData(Builtin):
6137
"""
6238
<url>:WMA link:https://reference.wolfram.com/language/ref/BoxData.html</url>
@@ -146,6 +122,7 @@ class GridBox(BoxExpression):
146122
# >> MathMLForm[TableForm[{{a,b},{c,d}}]]
147123
# = ...
148124
"""
125+
149126
options = {"ColumnAlignments": "Center"}
150127
summary_text = "low-level representation of an arbitrary 2D layout"
151128

mathics/builtin/forms/output.py

Lines changed: 20 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,35 @@
1212
"""
1313
Form Functions
1414
"""
15-
import re
16-
from math import ceil
1715
from typing import Optional
1816

19-
from mathics.builtin.box.layout import GridBox, RowBox, to_boxes
17+
from mathics.builtin.box.layout import RowBox
2018
from mathics.builtin.forms.base import FormBaseClass
21-
from mathics.builtin.makeboxes import MakeBoxes, NumberForm_to_String
22-
from mathics.builtin.tensors import get_dimensions
23-
from mathics.core.atoms import (
24-
Integer,
25-
MachineReal,
26-
PrecisionReal,
27-
Real,
28-
String,
29-
StringFromPython,
30-
)
19+
from mathics.core.atoms import Integer, Real, String, StringFromPython
3120
from mathics.core.builtin import Builtin
3221
from mathics.core.evaluation import Evaluation
33-
from mathics.core.expression import BoxError, Expression
22+
from mathics.core.expression import Expression
3423
from mathics.core.list import ListExpression
35-
from mathics.core.number import (
36-
LOG2_10,
37-
RECONSTRUCT_MACHINE_PRECISION_DIGITS,
38-
convert_base,
39-
dps,
40-
)
41-
from mathics.core.symbols import (
42-
Symbol,
43-
SymbolFalse,
44-
SymbolFullForm,
45-
SymbolList,
46-
SymbolNull,
47-
SymbolTrue,
48-
)
24+
from mathics.core.number import dps
25+
from mathics.core.symbols import Symbol, SymbolFalse, SymbolNull, SymbolTrue
4926
from mathics.core.systemsymbols import (
5027
SymbolAutomatic,
5128
SymbolInfinity,
5229
SymbolMakeBoxes,
5330
SymbolNumberForm,
54-
SymbolOutputForm,
5531
SymbolRowBox,
5632
SymbolRuleDelayed,
57-
SymbolSubscriptBox,
5833
SymbolSuperscriptBox,
5934
)
60-
from mathics.eval.makeboxes import StringLParen, StringRParen, format_element
61-
from mathics.eval.testing_expressions import expr_min
62-
63-
MULTI_NEWLINE_RE = re.compile(r"\n{2,}")
35+
from mathics.eval.makeboxes import (
36+
NumberForm_to_String,
37+
StringLParen,
38+
StringRParen,
39+
eval_baseform,
40+
eval_mathmlform,
41+
eval_tableform,
42+
eval_texform,
43+
)
6444

6545

6646
class BaseForm(FormBaseClass):
@@ -118,36 +98,7 @@ class BaseForm(FormBaseClass):
11898
def eval_makeboxes(self, expr, n, f, evaluation: Evaluation):
11999
"""MakeBoxes[BaseForm[expr_, n_],
120100
f:StandardForm|TraditionalForm|OutputForm]"""
121-
122-
base = n.get_int_value()
123-
if base <= 0:
124-
evaluation.message("BaseForm", "intpm", expr, n)
125-
return None
126-
127-
if isinstance(expr, PrecisionReal):
128-
x = expr.to_sympy()
129-
p = int(ceil(expr.get_precision() / LOG2_10) + 1)
130-
elif isinstance(expr, MachineReal):
131-
x = expr.value
132-
p = RECONSTRUCT_MACHINE_PRECISION_DIGITS
133-
elif isinstance(expr, Integer):
134-
x = expr.value
135-
p = 0
136-
else:
137-
return to_boxes(Expression(SymbolMakeBoxes, expr, f), evaluation)
138-
139-
try:
140-
val = convert_base(x, base, p)
141-
except ValueError:
142-
evaluation.message("BaseForm", "basf", n)
143-
return
144-
145-
if f is SymbolOutputForm:
146-
return to_boxes(String("%s_%d" % (val, base)), evaluation)
147-
else:
148-
return to_boxes(
149-
Expression(SymbolSubscriptBox, String(val), String(base)), evaluation
150-
)
101+
return eval_baseform(self, expr, n, f, evaluation)
151102

152103

153104
class FullForm(FormBaseClass):
@@ -208,29 +159,7 @@ class MathMLForm(FormBaseClass):
208159

209160
def eval_mathml(self, expr, evaluation) -> Expression:
210161
"MakeBoxes[expr_, MathMLForm]"
211-
212-
boxes = MakeBoxes(expr).evaluate(evaluation)
213-
try:
214-
mathml = boxes.boxes_to_mathml(evaluation=evaluation)
215-
except BoxError:
216-
evaluation.message(
217-
"General",
218-
"notboxes",
219-
Expression(SymbolFullForm, boxes).evaluate(evaluation),
220-
)
221-
mathml = ""
222-
is_a_picture = mathml[:6] == "<mtext"
223-
224-
# mathml = '<math><mstyle displaystyle="true">%s</mstyle></math>' % mathml
225-
# #convert_box(boxes)
226-
query = evaluation.parse("Settings`$UseSansSerif")
227-
usesansserif = query.evaluate(evaluation).to_python()
228-
if not is_a_picture:
229-
if isinstance(usesansserif, bool) and usesansserif:
230-
mathml = '<mstyle mathvariant="sans-serif">%s</mstyle>' % mathml
231-
232-
mathml = '<math display="block">%s</math>' % mathml # convert_box(boxes)
233-
return Expression(SymbolRowBox, ListExpression(String(mathml)))
162+
return eval_mathmlform(expr, evaluation)
234163

235164

236165
class InputForm(FormBaseClass):
@@ -297,9 +226,9 @@ def check_DigitBlock(self, value, evaluation: Evaluation):
297226
py_value = value.get_int_value()
298227
if value.sameQ(SymbolInfinity):
299228
return [0, 0]
300-
elif py_value is not None and py_value > 0:
229+
if py_value is not None and py_value > 0:
301230
return [py_value, py_value]
302-
elif value.has_form("List", 2):
231+
if value.has_form("List", 2):
303232
nleft, nright = value.elements
304233
py_left, py_right = nleft.get_int_value(), nright.get_int_value()
305234
if nleft.sameQ(SymbolInfinity):
@@ -707,27 +636,7 @@ class TeXForm(FormBaseClass):
707636

708637
def eval_tex(self, expr, evaluation) -> Expression:
709638
"MakeBoxes[expr_, TeXForm]"
710-
boxes = MakeBoxes(expr).evaluate(evaluation)
711-
try:
712-
# Here we set ``show_string_characters`` to False, to reproduce
713-
# the standard behaviour in WMA. Remove this parameter to recover the
714-
# quotes in InputForm and FullForm
715-
tex = boxes.boxes_to_tex(
716-
show_string_characters=False, evaluation=evaluation
717-
)
718-
719-
# Replace multiple newlines by a single one e.g. between asy-blocks
720-
tex = MULTI_NEWLINE_RE.sub("\n", tex)
721-
722-
tex = tex.replace(" \uF74c", " \\, d") # tmp hack for Integrate
723-
except BoxError:
724-
evaluation.message(
725-
"General",
726-
"notboxes",
727-
Expression(SymbolFullForm, boxes).evaluate(evaluation),
728-
)
729-
tex = ""
730-
return Expression(SymbolRowBox, ListExpression(String(tex)))
639+
return eval_texform(expr, evaluation)
731640

732641

733642
class TableForm(FormBaseClass):
@@ -777,51 +686,7 @@ class TableForm(FormBaseClass):
777686
def eval_makeboxes(self, table, f, evaluation, options):
778687
"""MakeBoxes[%(name)s[table_, OptionsPattern[%(name)s]],
779688
f:StandardForm|TraditionalForm|OutputForm]"""
780-
dims = len(get_dimensions(table, head=SymbolList))
781-
depth = self.get_option(options, "TableDepth", evaluation, pop=True)
782-
options["System`TableDepth"] = depth
783-
depth = expr_min((Integer(dims), depth))
784-
depth = depth.value
785-
if depth is None:
786-
evaluation.message(self.get_name(), "int")
787-
return
788-
789-
if depth <= 0:
790-
return format_element(table, evaluation, f)
791-
elif depth == 1:
792-
return GridBox(
793-
ListExpression(
794-
*(
795-
ListExpression(format_element(item, evaluation, f))
796-
for item in table.elements
797-
),
798-
)
799-
)
800-
# return Expression(
801-
# 'GridBox', Expression('List', *(
802-
# Expression('List', Expression('MakeBoxes', item, f))
803-
# for item in table.elements)))
804-
else:
805-
options["System`TableDepth"] = Integer(depth - 2)
806-
807-
def transform_item(item):
808-
if depth > 2:
809-
return self.eval_makeboxes(item, f, evaluation, options)
810-
else:
811-
return format_element(item, evaluation, f)
812-
813-
result = GridBox(
814-
ListExpression(
815-
*(
816-
ListExpression(
817-
*(transform_item(item) for item in row.elements),
818-
)
819-
for row in table.elements
820-
),
821-
)
822-
)
823-
options["System`TableDepth"] = Integer(depth)
824-
return result
689+
return eval_tableform(self, table, f, evaluation, options)
825690

826691

827692
class MatrixForm(TableForm):

0 commit comments

Comments
 (0)