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
1818from mathics .core .atoms import Integer , Integer1 , Real , String
1919from mathics .core .convert .op import operator_to_ascii , operator_to_unicode
2020from mathics .core .element import BaseElement
21+ from mathics .core .evaluation import Evaluation
2122from mathics .core .expression import Expression
2223from mathics .core .list import ListExpression
2324from mathics .core .symbols import Atom , Symbol
2425from mathics .core .systemsymbols import (
2526 SymbolFullForm ,
26- SymbolInfix ,
2727 SymbolInputForm ,
2828 SymbolLeft ,
2929 SymbolMakeBoxes ,
3030 SymbolNone ,
3131 SymbolOutputForm ,
3232 SymbolRight ,
33+ SymbolRowBox ,
3334)
34- from mathics .eval .makeboxes import (
35- eval_fullform_makeboxes ,
36- format_element ,
37- make_boxes_infix ,
38- )
35+ from mathics .eval .makeboxes import eval_fullform_makeboxes , format_element , parenthesize
3936
4037SymbolNonAssociative = Symbol ("System`NonAssociative" )
4138SymbolSubscriptBox = Symbol ("System`SubscriptBox" )
4239
4340
44- def eval_makeboxes_infix (
41+ ####################################################################
42+ # This section might get moved to mathics.box
43+ #
44+ # Some of the code below get replace Mathics code or may get put in
45+ # collection of boxing modules,
46+ # e.g. ``mathics.box.boxes_operators.box_infix()``.
47+ #
48+ ####################################################################
49+
50+
51+ def box_infix (
4552 expr : Expression ,
4653 operator : BaseElement ,
4754 form : Symbol ,
48- evaluation ,
49- precedence_value : Optional [int ] = None ,
55+ evaluation : Evaluation ,
56+ precedence_value : Optional [int ] = 0 ,
5057 grouping : Optional [str ] = None ,
51- ):
52- """Implements MakeBoxes[Infix[...]]."""
53-
54- # Actually, this function implements one part of the evaluation:
55- # the one that should be done at the "format" level. In that point,
56- # the operators are processed to add spaces and use the right
57- # encoding. This should be done at the level of the formatter, not
58- # in the "MakeBoxes" step.
59- # Then, the true implementation is done
60- # in ```mathics.eval.makeboxes.make_boxes_infix```.
61-
62- ## FIXME: this should go into a some formatter.
58+ ) -> Optional [Expression ]:
59+ """Implements MakeBoxes[Infix[...]].
60+ This function kicks off boxing for Infix operators.
61+
62+ Operators are processed to add spaces and to use the right encoding.
63+ """
64+
65+ # FIXME: this should go into a some formatter.
6366 def format_operator (operator ) -> Union [String , BaseElement ]:
6467 """
6568 Format infix operator `operator`. To do this outside parameter form is used.
@@ -95,7 +98,7 @@ def format_operator(operator) -> Union[String, BaseElement]:
9598 if len (elements ) > 1 :
9699 if operator .has_form ("List" , len (elements ) - 1 ):
97100 operator = [format_operator (op ) for op in operator .elements ]
98- return make_boxes_infix (
101+ return box_infix_elements (
99102 elements , operator , precedence_value , grouping , form
100103 )
101104 else :
@@ -113,17 +116,50 @@ def format_operator(operator) -> Union[String, BaseElement]:
113116 String (operator_to_unicode .get (op_str , op_str ))
114117 )
115118
116- return make_boxes_infix (elements , operator , precedence_value , grouping , form )
119+ return box_infix_elements (elements , operator , precedence_value , grouping , form )
117120
118121 elif len (elements ) == 1 :
119122 return MakeBoxes (elements [0 ], form )
120123 else :
121124 return MakeBoxes (expr , form )
122125
123126
127+ # FIXME: op should be a string, so remove the Union.
128+ def box_infix_elements (
129+ elements , op : Union [String , list ], precedence : int , grouping , form : Symbol
130+ ) -> Expression :
131+ result = []
132+ for index , element in enumerate (elements ):
133+ if index > 0 :
134+ if isinstance (op , list ):
135+ result .append (op [index - 1 ])
136+ else :
137+ result .append (op )
138+ parenthesized = False
139+ if grouping == "System`NonAssociative" :
140+ parenthesized = True
141+ elif grouping == "System`Left" and index > 0 :
142+ parenthesized = True
143+ elif grouping == "System`Right" and index == 0 :
144+ parenthesized = True
145+
146+ element_boxes = Expression (SymbolMakeBoxes , element , form )
147+ element = parenthesize (precedence , element , element_boxes , parenthesized )
148+
149+ result .append (element )
150+ return Expression (SymbolRowBox , ListExpression (* result ))
151+
152+
153+ ####################################################################
154+ # End of section of code that might be in mathics.box.
155+ ####################################################################
156+
157+
124158class Center (Builtin ):
125159 """
126- <url>:WMA link:https://reference.wolfram.com/language/ref/Center.html</url>
160+ <url>
161+ :WMA link:
162+ https://reference.wolfram.com/language/ref/Center.html</url>
127163
128164 <dl>
129165 <dt>'Center'
@@ -189,7 +225,7 @@ class Grid(Builtin):
189225 options = GridBox .options
190226 summary_text = " 2D layout containing arbitrary objects"
191227
192- def apply_makeboxes (self , array , f , evaluation , options ) -> Expression :
228+ def eval_makeboxes (self , array , f , evaluation : Evaluation , options ) -> Expression :
193229 """MakeBoxes[Grid[array_?MatrixQ, OptionsPattern[Grid]],
194230 f:StandardForm|TraditionalForm|OutputForm]"""
195231 return GridBox (
@@ -250,23 +286,23 @@ class Infix(Builtin):
250286
251287 # the right rule should be
252288 # mbexpression:MakeBoxes[Infix[___], form]
253- def eval_makeboxes (self , expression , form , evaluation ):
289+ def eval_makeboxes (self , expression , form , evaluation : Evaluation ):
254290 """MakeBoxes[Infix[___],
255291 form:StandardForm|TraditionalForm|OutputForm|InputForm]"""
256292 infix_expr = expression .elements [0 ]
257293 elements = list (infix_expr .elements )
258294 num_parms = len (elements )
259295
260296 if num_parms == 0 or num_parms > 4 :
261- evaluation .message ("Infix" , "argb" , Integer (len ( parms . get_sequence ()) ))
297+ evaluation .message ("Infix" , "argb" , Integer (num_parms ))
262298 return eval_fullform_makeboxes (infix_expr , evaluation , form )
263299
264300 if num_parms == 1 :
265301 expr = elements [0 ]
266- return eval_makeboxes_infix (expr , String ("~" ), form , evaluation )
302+ return box_infix (expr , String ("~" ), form , evaluation )
267303 if num_parms == 2 :
268304 expr , operator = elements
269- return eval_makeboxes_infix (expr , operator , form , evaluation )
305+ return box_infix (expr , operator , form , evaluation )
270306
271307 expr , operator , precedence = elements [:3 ]
272308 if not isinstance (precedence , Integer ):
@@ -279,11 +315,9 @@ def eval_makeboxes(self, expression, form, evaluation):
279315
280316 grouping = SymbolNone if num_parms < 4 else elements [3 ]
281317 if grouping is SymbolNone :
282- return eval_makeboxes_infix (
283- expr , operator , form , evaluation , precedence .value
284- )
318+ return box_infix (expr , operator , form , evaluation , precedence .value )
285319 if grouping in (SymbolNonAssociative , SymbolLeft , SymbolRight ):
286- return eval_makeboxes_infix (
320+ return box_infix (
287321 expr , operator , form , evaluation , precedence .value , grouping .get_name ()
288322 )
289323
@@ -297,7 +331,8 @@ class Left(Builtin):
297331
298332 <dl>
299333 <dt>'Left'
300- <dd>is used with operator formatting constructs to specify a left-associative operator.
334+ <dd>is used with operator formatting constructs to specify a \
335+ left-associative operator.
301336 </dl>
302337 """
303338
@@ -312,7 +347,8 @@ class NonAssociative(Builtin):
312347
313348 <dl>
314349 <dt>'NonAssociative'
315- <dd>is used with operator formatting constructs to specify a non-associative operator.
350+ <dd>is used with operator formatting constructs to specify a \
351+ non-associative operator.
316352 </dl>
317353 """
318354
@@ -371,7 +407,7 @@ class Precedence(Builtin):
371407
372408 summary_text = "an object to be parenthesized with a given precedence level"
373409
374- def apply (self , expr , evaluation ) -> Real :
410+ def eval (self , expr , evaluation ) -> Real :
375411 "Precedence[expr_]"
376412
377413 name = expr .get_name ()
@@ -429,7 +465,8 @@ class Right(Builtin):
429465
430466 <dl>
431467 <dt>'Right'
432- <dd>is used with operator formatting constructs to specify a right-associative operator.
468+ <dd>is used with operator formatting constructs to specify a \
469+ right-associative operator.
433470 </dl>
434471 """
435472
@@ -448,21 +485,21 @@ class Row(Builtin):
448485
449486 summary_text = "1D layouts containing arbitrary objects in a row"
450487
451- def apply_makeboxes (self , items , sep , f , evaluation ):
488+ def eval_makeboxes (self , items , sep , form , evaluation : Evaluation ):
452489 """MakeBoxes[Row[{items___}, sep_:""],
453- f :StandardForm|TraditionalForm|OutputForm]"""
490+ form :StandardForm|TraditionalForm|OutputForm]"""
454491
455492 items = items .get_sequence ()
456493 if not isinstance (sep , String ):
457- sep = MakeBoxes (sep , f )
494+ sep = MakeBoxes (sep , form )
458495 if len (items ) == 1 :
459- return MakeBoxes (items [0 ], f )
496+ return MakeBoxes (items [0 ], form )
460497 else :
461498 result = []
462499 for index , item in enumerate (items ):
463500 if index > 0 and not sep .sameQ (String ("" )):
464501 result .append (to_boxes (sep , evaluation ))
465- item = MakeBoxes (item , f ).evaluate (evaluation )
502+ item = MakeBoxes (item , form ).evaluate (evaluation )
466503 item = to_boxes (item , evaluation )
467504 result .append (item )
468505 return RowBox (* result )
@@ -475,22 +512,31 @@ class Style(Builtin):
475512 <dl>
476513 <dt>'Style[$expr$, options]'
477514 <dd>displays $expr$ formatted using the specified option settings.
515+
478516 <dt>'Style[$expr$, "style"]'
479517 <dd> uses the option settings for the specified style in the current notebook.
518+
480519 <dt>'Style[$expr$, $color$]'
481520 <dd>displays using the specified color.
521+
482522 <dt>'Style[$expr$, $Bold$]'
483523 <dd>displays with fonts made bold.
524+
484525 <dt>'Style[$expr$, $Italic$]'
485526 <dd>displays with fonts made italic.
527+
486528 <dt>'Style[$expr$, $Underlined$]'
487529 <dd>displays with fonts underlined.
530+
488531 <dt>'Style[$expr$, $Larger$]
489532 <dd>displays with fonts made larger.
533+
490534 <dt>'Style[$expr$, $Smaller$]'
491535 <dd>displays with fonts made smaller.
536+
492537 <dt>'Style[$expr$, $n$]'
493538 <dd>displays with font size n.
539+
494540 <dt>'Style[$expr$, $Tiny$]'
495541 <dt>'Style[$expr$, $Small$]', etc.
496542 <dd>display with fonts that are tiny, small, etc.
@@ -523,7 +569,7 @@ class Subscript(Builtin):
523569
524570 summary_text = "format an expression with a subscript"
525571
526- def apply_makeboxes (self , x , y , f , evaluation ) -> Expression :
572+ def eval_makeboxes (self , x , y , f , evaluation ) -> Expression :
527573 "MakeBoxes[Subscript[x_, y__], f:StandardForm|TraditionalForm]"
528574
529575 y = y .get_sequence ()
@@ -536,7 +582,9 @@ def apply_makeboxes(self, x, y, f, evaluation) -> Expression:
536582
537583class Subsuperscript (Builtin ):
538584 """
539- <url>:WMA link:https://reference.wolfram.com/language/ref/Subsuperscript.html</url>
585+ <url>
586+ :WMA link:
587+ https://reference.wolfram.com/language/ref/Subsuperscript.html</url>
540588
541589 <dl>
542590 <dt>'Subsuperscript[$a$, $b$, $c$]'
@@ -558,7 +606,9 @@ class Subsuperscript(Builtin):
558606
559607class Superscript (Builtin ):
560608 """
561- <url>:WMA link:https://reference.wolfram.com/language/ref/Superscript.html</url>
609+ <url>
610+ :WMA link:
611+ https://reference.wolfram.com/language/ref/Superscript.html</url>
562612
563613 <dl>
564614 <dt>'Superscript[$x$, $y$]'
0 commit comments