@@ -102,8 +102,7 @@ def contribute(self, definitions, is_pymodule=False):
102102 # used, so it won't work.
103103 if option not in definitions .builtin :
104104 definitions .builtin [option ] = Definition (
105- name = name , attributes = set ()
106- )
105+ name = name , attributes = set ())
107106
108107 # Check if the given options are actually supported by the Builtin.
109108 # If not, we might issue an optx error and abort. Using '$OptionSyntax'
@@ -247,8 +246,7 @@ def contextify_form_name(f):
247246 # used, so it won't work.
248247 if option not in definitions .builtin :
249248 definitions .builtin [option ] = Definition (
250- name = name , attributes = set ()
251- )
249+ name = name , attributes = set ())
252250 defaults = []
253251 for spec , value in self .defaults .items ():
254252 value = parse_builtin_rule (value )
@@ -364,7 +362,7 @@ def get_option_string(self, *params):
364362 return None , s
365363
366364
367- class InstancableBuiltin (Builtin ):
365+ class InstanceableBuiltin (Builtin ):
368366 def __new__ (cls , * args , ** kwargs ):
369367 new_kwargs = kwargs .copy ()
370368 new_kwargs ["expression" ] = False
@@ -377,7 +375,7 @@ def __new__(cls, *args, **kwargs):
377375 try :
378376 instance .init (* args , ** kwargs )
379377 except TypeError :
380- # TypeError occurs when unpickling instance, e.g. PatterObject ,
378+ # TypeError occurs when unpickling instance, e.g. PatternObject ,
381379 # because parameter expr is not given. This should no be a
382380 # problem, as pickled objects need their init-method not
383381 # being called.
@@ -592,11 +590,101 @@ class BoxConstructError(Exception):
592590 pass
593591
594592
595- class BoxConstruct (Builtin ):
596- def get_option_values (self , leaves , evaluation = None , ** options ):
597- default = evaluation .definitions .get_options (self .get_name ()).copy ()
598- options = Expression ("List" , * leaves ).get_option_values (evaluation )
599- default .update (options )
593+ class BoxConstruct (InstanceableBuiltin ):
594+ def __new__ (cls , * leaves , ** kwargs ):
595+ instance = super ().__new__ (cls , * leaves , ** kwargs )
596+ instance ._leaves = leaves
597+ return instance
598+
599+ def evaluate (self , evaluation ):
600+ # THINK about: Should we evaluate the leaves here?
601+ return
602+
603+ def get_head_name (self ):
604+ return self .get_name ()
605+
606+ def get_lookup_name (self ):
607+ return self .get_name ()
608+
609+ def get_string_value (self ):
610+ return "-@" + self .get_head_name () + "@-"
611+
612+ def same (self , expr ):
613+ return expr .same (self )
614+
615+ def is_atom (self ):
616+ return False
617+
618+ def do_format (self , evaluation , format ):
619+ return self
620+
621+ def format (self , evaluation , fmt ):
622+ return self
623+
624+ def get_head (self ):
625+ return Symbol (self .get_name ())
626+
627+ @property
628+ def head (self ):
629+ return self .get_head ()
630+
631+ @head .setter
632+ def head (self , value ):
633+ raise ValueError ('BoxConstruct.head is write protected.' )
634+
635+ @property
636+ def leaves (self ):
637+ return self ._leaves
638+
639+ @leaves .setter
640+ def leaves (self , value ):
641+ raise ValueError ('BoxConstruct.leaves is write protected.' )
642+
643+ # I need to repeat this, because this is not
644+ # an expression...
645+ def has_form (self , heads , * leaf_counts ):
646+ """
647+ leaf_counts:
648+ (,): no leaves allowed
649+ (None,): no constraint on number of leaves
650+ (n, None): leaf count >= n
651+ (n1, n2, ...): leaf count in {n1, n2, ...}
652+ """
653+
654+ head_name = self .get_name ()
655+ if isinstance (heads , (tuple , list , set )):
656+ if head_name not in [ensure_context (h ) for h in heads ]:
657+ return False
658+ else :
659+ if head_name != ensure_context (heads ):
660+ return False
661+ if not leaf_counts :
662+ return False
663+ if leaf_counts and leaf_counts [0 ] is not None :
664+ count = len (self ._leaves )
665+ if count not in leaf_counts :
666+ if (len (leaf_counts ) == 2 and # noqa
667+ leaf_counts [1 ] is None and count >= leaf_counts [0 ]):
668+ return True
669+ else :
670+ return False
671+ return True
672+
673+ def flatten_pattern_sequence (self , evaluation ) -> 'BoxConstruct' :
674+ return self
675+
676+ def get_option_values (self , leaves , ** options ):
677+ evaluation = options .get ("evaluation" , None )
678+ if evaluation :
679+ default = evaluation .definitions .get_options (self .get_name ()).copy ()
680+ options = Expression ("List" , * leaves ).get_option_values (evaluation )
681+ default .update (options )
682+ else :
683+ from mathics .core .parser import parse_builtin_rule
684+ default = {}
685+ for option , value in self .options .items ():
686+ option = ensure_context (option )
687+ default [option ] = parse_builtin_rule (value )
600688 return default
601689
602690 def boxes_to_text (self , leaves , ** options ) -> str :
@@ -619,7 +707,7 @@ def __init__(self, name, count, expected):
619707 super ().__init__ (None , None )
620708
621709
622- class PatternObject (InstancableBuiltin , Pattern ):
710+ class PatternObject (InstanceableBuiltin , Pattern ):
623711 needs_verbatim = True
624712
625713 arg_counts : typing .List [int ] = []
0 commit comments