11# -*- coding: utf-8 -*-
22
33"""
4- This module contains symbols used to define the high level layout for
4+ This module contains symbols used to define the high level layout for \
55 expression formatting.
66
7- For instance, to represent a set of consecutive expressions in a row,
8- we can use ``Row``
7+ For instance, to represent a set of consecutive expressions in a row, \
8+ we can use ``Row``.
99
1010"""
1111from typing import Optional , Union
1515from mathics .builtin .lists import list_boxes
1616from mathics .builtin .makeboxes import MakeBoxes
1717from mathics .builtin .options import options_to_rules
18- from mathics .core .atoms import Real , String
18+ from mathics .core .atoms import Integer , Integer1 , Real , String
1919from mathics .core .expression import Evaluation , Expression
20+ from mathics .core .convert .op import operator_to_ascii , operator_to_unicode
21+ from mathics .core .element import BaseElement
2022from mathics .core .list import ListExpression
2123from mathics .core .symbols import Atom , Symbol
2224from mathics .core .systemsymbols import (
2325 SymbolFullForm ,
24- SymbolInfix ,
2526 SymbolInputForm ,
2627 SymbolLeft ,
2728 SymbolMakeBoxes ,
2829 SymbolNone ,
2930 SymbolOutputForm ,
3031 SymbolRight ,
32+ SymbolRowBox ,
3133)
32- from mathics .eval .makeboxes import (
33- eval_fullform_makeboxes ,
34- format_element ,
35- make_boxes_infix ,
36- )
34+ from mathics .eval .makeboxes import eval_fullform_makeboxes , format_element , parenthesize
3735
3836SymbolNonAssociative = Symbol ("System`NonAssociative" )
3937SymbolSubscriptBox = Symbol ("System`SubscriptBox" )
4038
4139
42- def eval_makeboxes_infix (
40+ ####################################################################
41+ # This section might get moved to mathics.box
42+ #
43+ # Some of the code below get replace Mathics code or may get put in
44+ # collection of boxing modules,
45+ # e.g. ``mathics.box.boxes_operators.box_infix()``.
46+ #
47+ ####################################################################
48+
49+
50+ def box_infix (
4351 expr : Expression ,
4452 operator : BaseElement ,
4553 form : Symbol ,
46- evaluation ,
47- precedence_value : Optional [int ] = None ,
54+ evaluation : Evaluation ,
55+ precedence_value : Optional [int ] = 0 ,
4856 grouping : Optional [str ] = None ,
49- ):
50- """Implements MakeBoxes[Infix[...]]."""
51-
52- # Actually, this function implements one part of the evaluation:
53- # the one that should be done at the "format" level. In that point,
54- # the operators are processed to add spaces and use the right
55- # encoding. This should be done at the level of the formatter, not
56- # in the "MakeBoxes" step.
57- # Then, the true implementation is done
58- # in ```mathics.eval.makeboxes.make_boxes_infix```.
59-
60- ## FIXME: this should go into a some formatter.
57+ ) -> Optional [Expression ]:
58+ """Implements MakeBoxes[Infix[...]].
59+ This function kicks off boxing for Infix operators.
60+
61+ Operators are processed to add spaces and to use the right encoding.
62+ """
63+
64+ # FIXME: this should go into a some formatter.
6165 def format_operator (operator ) -> Union [String , BaseElement ]:
6266 """
6367 Format infix operator `operator`. To do this outside parameter form is used.
@@ -93,7 +97,7 @@ def format_operator(operator) -> Union[String, BaseElement]:
9397 if len (elements ) > 1 :
9498 if operator .has_form ("List" , len (elements ) - 1 ):
9599 operator = [format_operator (op ) for op in operator .elements ]
96- return make_boxes_infix (
100+ return box_infix_elements (
97101 elements , operator , precedence_value , grouping , form
98102 )
99103 else :
@@ -111,17 +115,50 @@ def format_operator(operator) -> Union[String, BaseElement]:
111115 String (operator_to_unicode .get (op_str , op_str ))
112116 )
113117
114- return make_boxes_infix (elements , operator , precedence_value , grouping , form )
118+ return box_infix_elements (elements , operator , precedence_value , grouping , form )
115119
116120 elif len (elements ) == 1 :
117121 return MakeBoxes (elements [0 ], form )
118122 else :
119123 return MakeBoxes (expr , form )
120124
121125
126+ # FIXME: op should be a string, so remove the Union.
127+ def box_infix_elements (
128+ elements , op : Union [String , list ], precedence : int , grouping , form : Symbol
129+ ) -> Expression :
130+ result = []
131+ for index , element in enumerate (elements ):
132+ if index > 0 :
133+ if isinstance (op , list ):
134+ result .append (op [index - 1 ])
135+ else :
136+ result .append (op )
137+ parenthesized = False
138+ if grouping == "System`NonAssociative" :
139+ parenthesized = True
140+ elif grouping == "System`Left" and index > 0 :
141+ parenthesized = True
142+ elif grouping == "System`Right" and index == 0 :
143+ parenthesized = True
144+
145+ element_boxes = Expression (SymbolMakeBoxes , element , form )
146+ element = parenthesize (precedence , element , element_boxes , parenthesized )
147+
148+ result .append (element )
149+ return Expression (SymbolRowBox , ListExpression (* result ))
150+
151+
152+ ####################################################################
153+ # End of section of code that might be in mathics.box.
154+ ####################################################################
155+
156+
122157class Center (Builtin ):
123158 """
124- <url>:WMA link:https://reference.wolfram.com/language/ref/Center.html</url>
159+ <url>
160+ :WMA link:
161+ https://reference.wolfram.com/language/ref/Center.html</url>
125162
126163 <dl>
127164 <dt>'Center'
@@ -187,7 +224,7 @@ class Grid(Builtin):
187224 options = GridBox .options
188225 summary_text = " 2D layout containing arbitrary objects"
189226
190- def eval_makeboxes (self , array , f , evaluation , options ) -> Expression :
227+ def eval_makeboxes (self , array , f , evaluation : Evaluation , options ) -> Expression :
191228 """MakeBoxes[Grid[array_?MatrixQ, OptionsPattern[Grid]],
192229 f:StandardForm|TraditionalForm|OutputForm]"""
193230 return GridBox (
@@ -248,23 +285,23 @@ class Infix(Builtin):
248285
249286 # the right rule should be
250287 # mbexpression:MakeBoxes[Infix[___], form]
251- def eval_makeboxes (self , expression , form , evaluation ):
288+ def eval_makeboxes (self , expression , form , evaluation : Evaluation ):
252289 """MakeBoxes[Infix[___],
253290 form:StandardForm|TraditionalForm|OutputForm|InputForm]"""
254291 infix_expr = expression .elements [0 ]
255292 elements = list (infix_expr .elements )
256293 num_parms = len (elements )
257294
258295 if num_parms == 0 or num_parms > 4 :
259- evaluation .message ("Infix" , "argb" , Integer (len ( parms . get_sequence ()) ))
296+ evaluation .message ("Infix" , "argb" , Integer (num_parms ))
260297 return eval_fullform_makeboxes (infix_expr , evaluation , form )
261298
262299 if num_parms == 1 :
263300 expr = elements [0 ]
264- return eval_makeboxes_infix (expr , String ("~" ), form , evaluation )
301+ return box_infix (expr , String ("~" ), form , evaluation )
265302 if num_parms == 2 :
266303 expr , operator = elements
267- return eval_makeboxes_infix (expr , operator , form , evaluation )
304+ return box_infix (expr , operator , form , evaluation )
268305
269306 expr , operator , precedence = elements [:3 ]
270307 if not isinstance (precedence , Integer ):
@@ -277,11 +314,9 @@ def eval_makeboxes(self, expression, form, evaluation):
277314
278315 grouping = SymbolNone if num_parms < 4 else elements [3 ]
279316 if grouping is SymbolNone :
280- return eval_makeboxes_infix (
281- expr , operator , form , evaluation , precedence .value
282- )
317+ return box_infix (expr , operator , form , evaluation , precedence .value )
283318 if grouping in (SymbolNonAssociative , SymbolLeft , SymbolRight ):
284- return eval_makeboxes_infix (
319+ return box_infix (
285320 expr , operator , form , evaluation , precedence .value , grouping .get_name ()
286321 )
287322
@@ -295,7 +330,8 @@ class Left(Builtin):
295330
296331 <dl>
297332 <dt>'Left'
298- <dd>is used with operator formatting constructs to specify a left-associative operator.
333+ <dd>is used with operator formatting constructs to specify a \
334+ left-associative operator.
299335 </dl>
300336 """
301337
@@ -310,7 +346,8 @@ class NonAssociative(Builtin):
310346
311347 <dl>
312348 <dt>'NonAssociative'
313- <dd>is used with operator formatting constructs to specify a non-associative operator.
349+ <dd>is used with operator formatting constructs to specify a \
350+ non-associative operator.
314351 </dl>
315352 """
316353
@@ -427,7 +464,8 @@ class Right(Builtin):
427464
428465 <dl>
429466 <dt>'Right'
430- <dd>is used with operator formatting constructs to specify a right-associative operator.
467+ <dd>is used with operator formatting constructs to specify a \
468+ right-associative operator.
431469 </dl>
432470 """
433471
@@ -446,21 +484,21 @@ class Row(Builtin):
446484
447485 summary_text = "1D layouts containing arbitrary objects in a row"
448486
449- def eval_makeboxes (self , items , sep , f , evaluation : Evaluation ):
487+ def eval_makeboxes (self , items , sep , form , evaluation : Evaluation ):
450488 """MakeBoxes[Row[{items___}, sep_:""],
451- f :StandardForm|TraditionalForm|OutputForm]"""
489+ form :StandardForm|TraditionalForm|OutputForm]"""
452490
453491 items = items .get_sequence ()
454492 if not isinstance (sep , String ):
455- sep = MakeBoxes (sep , f )
493+ sep = MakeBoxes (sep , form )
456494 if len (items ) == 1 :
457- return MakeBoxes (items [0 ], f )
495+ return MakeBoxes (items [0 ], form )
458496 else :
459497 result = []
460498 for index , item in enumerate (items ):
461499 if index > 0 and not sep .sameQ (String ("" )):
462500 result .append (to_boxes (sep , evaluation ))
463- item = MakeBoxes (item , f ).evaluate (evaluation )
501+ item = MakeBoxes (item , form ).evaluate (evaluation )
464502 item = to_boxes (item , evaluation )
465503 result .append (item )
466504 return RowBox (* result )
@@ -473,22 +511,31 @@ class Style(Builtin):
473511 <dl>
474512 <dt>'Style[$expr$, options]'
475513 <dd>displays $expr$ formatted using the specified option settings.
514+
476515 <dt>'Style[$expr$, "style"]'
477516 <dd> uses the option settings for the specified style in the current notebook.
517+
478518 <dt>'Style[$expr$, $color$]'
479519 <dd>displays using the specified color.
520+
480521 <dt>'Style[$expr$, $Bold$]'
481522 <dd>displays with fonts made bold.
523+
482524 <dt>'Style[$expr$, $Italic$]'
483525 <dd>displays with fonts made italic.
526+
484527 <dt>'Style[$expr$, $Underlined$]'
485528 <dd>displays with fonts underlined.
529+
486530 <dt>'Style[$expr$, $Larger$]
487531 <dd>displays with fonts made larger.
532+
488533 <dt>'Style[$expr$, $Smaller$]'
489534 <dd>displays with fonts made smaller.
535+
490536 <dt>'Style[$expr$, $n$]'
491537 <dd>displays with font size n.
538+
492539 <dt>'Style[$expr$, $Tiny$]'
493540 <dt>'Style[$expr$, $Small$]', etc.
494541 <dd>display with fonts that are tiny, small, etc.
@@ -536,7 +583,9 @@ def eval_makeboxes(self, x, y, f, evaluation) -> Expression:
536583
537584class Subsuperscript (Builtin ):
538585 """
539- <url>:WMA link:https://reference.wolfram.com/language/ref/Subsuperscript.html</url>
586+ <url>
587+ :WMA link:
588+ https://reference.wolfram.com/language/ref/Subsuperscript.html</url>
540589
541590 <dl>
542591 <dt>'Subsuperscript[$a$, $b$, $c$]'
@@ -558,7 +607,9 @@ class Subsuperscript(Builtin):
558607
559608class Superscript (Builtin ):
560609 """
561- <url>:WMA link:https://reference.wolfram.com/language/ref/Superscript.html</url>
610+ <url>
611+ :WMA link:
612+ https://reference.wolfram.com/language/ref/Superscript.html</url>
562613
563614 <dl>
564615 <dt>'Superscript[$x$, $y$]'
0 commit comments