@@ -260,6 +260,18 @@ def init_instructions(self):
260260 'CMD' : self .handle_cmd ,
261261 'TEST' : self .handle_test_cmd ,
262262
263+ 'EXECAS' : self .handle_execute_as ,
264+ 'EXECASN' : self .handle_execute_as_not ,
265+ 'EXECAT' : self .handle_execute_at ,
266+ 'EXECATP' : self .handle_execute_at_position ,
267+ 'EXECPOS' : self .handle_execute_position ,
268+ 'EXECALI' : self .handle_execute_align ,
269+ 'EXECFACP' : self .handle_execute_face_pos ,
270+ 'EXECFAC' : self .handle_execute_face_entity ,
271+ 'EXECROT' : self .handle_execute_rotate ,
272+ 'EXECROTE' : self .handle_execute_rotate_entity ,
273+ 'EXECANC' : self .handle_execute_anchor ,
274+
263275 'PUSH' : self .handle_push ,
264276 'POP' : self .handle_pop ,
265277
@@ -676,6 +688,106 @@ def handle_print(self, arg1, *args):
676688 def handle_cmd (self , cmd ):
677689 self .add_command (Cmd (cmd ))
678690
691+ def _read_selector (self , sel_type , pairs ):
692+ assert sel_type [0 ] == 'string'
693+ assert len (pairs ) % 2 == 0
694+ simple = {}
695+ sel_args = None
696+ for i in range (0 , len (pairs ), 2 ):
697+ key_type , key = pairs [i ]
698+ val_type , val = pairs [i + 1 ]
699+ assert val_type == 'string'
700+ if key_type == 'string' :
701+ simple [key ] = val
702+ elif key_type == 'symbol' :
703+ # Special case where an entity local can be queried
704+ var = self .get_const (key )
705+ assert isinstance (var , EntityLocal )
706+ min , max = map (lambda v : int (v ) if v else None , val .split ('..' )) \
707+ if '..' in val else [int (val )]* 2
708+ sel_args = ComboSelectorArgs (sel_args , SelRange (var , min , max ))
709+ else :
710+ assert False , "Bad key type: " + pairs [i ]
711+ if simple :
712+ sel_args = ComboSelectorArgs (sel_args , SimpleSelectorArgs (simple ))
713+ return Selector (sel_type [1 ], sel_args )
714+
715+ def _read_pos (self , x , y , z ):
716+ coords = []
717+ for coord in (x , y , z ):
718+ type_ , val = coord
719+ if type_ == 'string' :
720+ assert val , "Empty string"
721+ assert val [0 ] in '~^' , "Invalid pos string '%s'" % val
722+ if len (val ) > 1 :
723+ # check it can parse as a float
724+ float (val [1 :])
725+ else :
726+ ref = self .resolve_ref (type_ , val )
727+ assert type (ref ) == int , "Unknown type %s %s" % (type (ref ), ref )
728+ val = ref
729+ coords .append (val )
730+ return Pos (* coords )
731+
732+ def _execute_chain_helper (self , lbl , chain ):
733+ arg_type , symbol = lbl
734+ assert arg_type == 'symbol'
735+ exec_func = self .symbol_to_func (symbol )
736+ self .add_command (chain .run (Function (exec_func )))
737+
738+ def do_execute_as (self , lbl , sel_type , pairs , inverse ):
739+ chain = ExecuteChain ()
740+ if inverse :
741+ chain = chain .cond ('unless' )
742+ selector = self ._read_selector (sel_type , pairs )
743+ self ._execute_chain_helper (lbl , chain .where (selector ))
744+
745+ def handle_execute_as (self , lbl , sel_type , * pairs ):
746+ self .do_execute_as (lbl , sel_type , pairs , False )
747+
748+ def handle_execute_as_not (self , lbl , sel_type , * pairs ):
749+ self .do_execute_as (lbl , sel_type , pairs , True )
750+
751+ def handle_execute_at (self , lbl , sel_type , * pairs ):
752+ self ._execute_chain_helper (lbl , ExecuteChain ().at (
753+ self ._read_selector (sel_type , pairs )))
754+
755+ def handle_execute_at_position (self , lbl , sel_type , * pairs ):
756+ self ._execute_chain_helper (lbl , ExecuteChain ().at_entity_pos (
757+ self ._read_selector (sel_type , pairs )))
758+
759+ def handle_execute_position (self , lbl , x , y , z ):
760+ self ._execute_chain_helper (lbl , ExecuteChain ().at_pos (
761+ self ._read_pos (x , y , z )))
762+
763+ def handle_execute_align (self , lbl , axes ):
764+ arg_type , axes = axes
765+ assert arg_type == 'string'
766+ self ._execute_chain_helper (lbl , ExecuteChain ().align (axes ))
767+
768+ def handle_execute_face_pos (self , lbl , x , y , z ):
769+ self ._execute_chain_helper (lbl , ExecuteChain ().facing (
770+ self ._read_pos (x , y , z )))
771+
772+ def handle_execute_face_entity (self , lbl , sel_type , * pairs ):
773+ self ._execute_chain_helper (lbl , ExecuteChain ().facing_entity (
774+ self ._read_selector (sel_type , pairs )))
775+
776+ def handle_execute_rotate (self , lbl , y , x ):
777+ y , x = self .resolve_ref (* y ), self .resolve_ref (* x )
778+ assert type (y ) == int
779+ assert type (x ) == int
780+ self ._execute_chain_helper (lbl , ExecuteChain ().rotated (y , x ))
781+
782+ def handle_execute_rotate_entity (self , lbl , sel_type , * pairs ):
783+ self ._execute_chain_helper (lbl , ExecuteChain ().rotated_as_entity (
784+ self ._read_selector (sel_type , pairs )))
785+
786+ def handle_execute_anchor (self , lbl , anchor ):
787+ arg_type , anchor = anchor
788+ assert arg_type == 'string'
789+ self ._execute_chain_helper (lbl , ExecuteChain ().anchored (anchor ))
790+
679791 def handle_push (self ):
680792 self .add_command (Function ('stack_push_0' ))
681793
0 commit comments