def add_state(self, StateIndex, OnSuccessDoorId, OnFailureDoorId, BeforeReload=None): """Adds a state from where the reload state is entered. When reload is done it jumps to 'OnFailureDoorId' if the reload failed and to 'OnSuccessDoorId' if the reload succeeded. RETURNS: DoorID into the reload state. Jump to this DoorID in order to trigger the reload for the state given by 'StateIndex'. """ assert BeforeReload is None or isinstance(BeforeReload, OpList) # Before reload: prepare after reload, the jump back to the reloading state. before_cl = OpList(Op.PrepareAfterReload(OnSuccessDoorId, OnFailureDoorId)) if BeforeReload is not None: # May be, add additional commands before_cl = before_cl.concatinate(BeforeReload) # No two transitions into the reload state have the same OpList! # No two transitions can have the same DoorID! # => it is safe to assign a new DoorID withouth .categorize() ta = TransitionAction(before_cl) # Assign a DoorID (without categorization) knowing that no such entry # into this state existed before. ta.door_id = dial_db.new_door_id(self.index) assert not self.entry.has_transition(self.index, StateIndex) # Cannot be in there twice! self.entry.enter(self.index, StateIndex, ta) return ta.door_id
def get_Analyzer(StatesDescription): """StatesDescription: List of pairs: (state index, transition map) That is, it tells what state of a given state index has what transition map. The transition map is a list of pairs (interval, target state index) """ # Use 'BACKWARD_PRE_CONTEXT' so that the drop-out objects are created # without larger analysis. init_state_index = 7777L analyzer = Analyzer(engine.BACKWARD_PRE_CONTEXT, init_state_index) all_state_index_set = set() for state_index, transition_map in StatesDescription: assert isinstance(state_index, long) assert isinstance(transition_map, list) tm = TransitionMap.from_iterable(transition_map) tm.fill_gaps(E_StateIndices.DROP_OUT, Setup.buffer_codec.drain_set.minimum(), Setup.buffer_codec.drain_set.supremum()) analyzer.state_db[state_index] = get_AnalyzerState(state_index, tm) all_state_index_set.update(x[1] for x in transition_map) # 'Dummy' transitions from init state to all analyzer.state_db[init_state_index] = get_AnalyzerState_Init( init_state_index, [x[0] for x in StatesDescription]) # Make sure, that all states mentioned in the transition map really exist. for i in all_state_index_set: if i in analyzer.state_db: continue analyzer.state_db[i] = get_AnalyzerState( i, TransitionMap.from_iterable([])) # Make sure, that the transitions appear in the 'entry' member of the # states. Collect transition information. for state_index, transition_map in StatesDescription: for interval, target_index in transition_map: if not isinstance(target_index, (long, int)): continue analyzer.state_db[target_index].entry.enter( target_index, state_index, TransitionAction()) analyzer.state_db[state_index].entry.enter(state_index, init_state_index, TransitionAction()) for state in analyzer.state_db.itervalues(): state.entry.categorize(state.index) # Make sure that every state has its entry into drop-out empty_cl = OpList() for i in analyzer.state_db.iterkeys(): analyzer.drop_out.entry.enter_OpList(E_StateIndices.DROP_OUT, i, copy(empty_cl)) analyzer.drop_out.entry.categorize(E_StateIndices.DROP_OUT) analyzer.prepare_DoorIDs() return analyzer
def prepare_state(self, OldState, StateIndex, OnBeforeEntry): """Prepares states to increment the input/read pointer and dereferences it to access the lexatom for the state transition triggering. REQUIRES: 'self.init_state_forward_f', 'self.engine_type', 'self.__from_db'. """ state = FSM_State.from_State(OldState, StateIndex, self.engine_type, self.dial_db) cmd_list = [] if self.engine_type.is_BACKWARD_PRE_CONTEXT(): cmd_list.extend( Op.PreContextOK(cmd.acceptance_id()) for cmd in OldState.single_entry.get_iterable(SeAccept)) if state.transition_map is None and False: # NOTE: We need a way to disable this exception for PathWalkerState-s(!) # It's safe, not to allow it, in general. #------------------------------------------------------------------------ # If the state has no further transitions then the input character does # not have to be read. This is so, since without a transition map, the # state immediately drops out. The drop out transits to a terminal. # Then, the next action will happen from the init state where we work # on the same position. If required the reload happens at that moment, # NOT before the empty transition block. # # This is not true for Path Walker States, so we offer the option # 'ForceInputDereferencingF' assert StateIndex != self.init_state_index # Empty state machine! --> impossible if self.engine_type.is_FORWARD(): cmd_ext = [Op.Increment(E_R.InputP)] else: cmd_ext = [Op.Decrement(E_R.InputP)] else: if self.engine_type.is_FORWARD(): cmd_ext = [Op.Increment(E_R.InputP), Op.InputPDereference()] else: cmd_ext = [Op.Decrement(E_R.InputP), Op.InputPDereference()] cmd_list.extend(cmd_ext) ta = TransitionAction(OpList.from_iterable(cmd_list)) # NOTE: The 'from reload transition' is implemented by 'prepare_for_reload()' for source_state_index in self.__from_db[StateIndex]: assert source_state_index != E_StateIndices.BEFORE_ENTRY state.entry.enter(StateIndex, source_state_index, ta.clone()) if StateIndex == self.init_state_index: if self.engine_type.is_FORWARD(): on_entry_op_list = OnBeforeEntry.clone() on_entry_op_list.append(Op.InputPDereference()) ta = TransitionAction(on_entry_op_list) state.entry.enter_state_machine_entry(self.__state_machine_id, StateIndex, ta) return state
def prepare_state(self, OldState, StateIndex, OnBeforeEntry): """REQUIRES: 'self.init_state_forward_f', 'self.engine_type', 'self.__from_db'. """ state = AnalyzerState.from_State(OldState, StateIndex, self.engine_type) cmd_list = [] if self.engine_type.is_BACKWARD_PRE_CONTEXT(): cmd_list.extend( Op.PreContextOK(cmd.acceptance_id()) for cmd in OldState.single_entry.get_iterable(SeAccept) ) if state.transition_map is None and False: # NOTE: We need a way to disable this exception for PathWalkerState-s(!) # It's safe, not to allow it, in general. #------------------------------------------------------------------------ # If the state has no further transitions then the input character does # not have to be read. This is so, since without a transition map, the # state immediately drops out. The drop out transits to a terminal. # Then, the next action will happen from the init state where we work # on the same position. If required the reload happens at that moment, # NOT before the empty transition block. # # This is not true for Path Walker States, so we offer the option # 'ForceInputDereferencingF' assert StateIndex != self.init_state_index # Empty state machine! --> impossible if self.engine_type.is_FORWARD(): cmd_ext = [ Op.Increment(E_R.InputP) ] else: cmd_ext = [ Op.Decrement(E_R.InputP) ] else: if self.engine_type.is_FORWARD(): cmd_ext = [ Op.Increment(E_R.InputP), Op.InputPDereference() ] else: cmd_ext = [ Op.Decrement(E_R.InputP), Op.InputPDereference() ] cmd_list.extend(cmd_ext) ta = TransitionAction(OpList.from_iterable(cmd_list)) # NOTE: The 'from reload transition' is implemented by 'prepare_for_reload()' for source_state_index in self.__from_db[StateIndex]: assert source_state_index != E_StateIndices.BEFORE_ENTRY state.entry.enter(StateIndex, source_state_index, ta.clone()) if StateIndex == self.init_state_index: if self.engine_type.is_FORWARD(): on_entry_op_list = OnBeforeEntry.clone() on_entry_op_list.append(Op.InputPDereference()) ta = TransitionAction(on_entry_op_list) state.entry.enter_state_machine_entry(self.__state_machine_id, StateIndex, ta) return state
def prepare_state(self, OldState, StateIndex): """REQUIRES: 'self.init_state_forward_f', 'self.engine_type', 'self.__from_db'. """ state = AnalyzerState.from_State(OldState, StateIndex, self.engine_type) cmd_list = [] if self.engine_type.is_BACKWARD_PRE_CONTEXT(): cmd_list.extend( PreContextOK(origin.acceptance_id()) for origin in OldState.origins() \ if origin.is_acceptance() ) if state.transition_map is None and False: # NOTE: We need a way to disable this exception for PathWalkerState-s(!) # It's safe, not to allow it, in general. #------------------------------------------------------------------------ # If the state has no further transitions then the input character does # not have to be read. This is so, since without a transition map, the # state immediately drops out. The drop out transits to a terminal. # Then, the next action will happen from the init state where we work # on the same position. If required the reload happens at that moment, # NOT before the empty transition block. # # This is not true for Path Walker States, so we offer the option # 'ForceInputDereferencingF' assert StateIndex != self.init_state_index # Empty state machine! --> impossible if self.engine_type.is_FORWARD(): cmd_list.append(InputPIncrement()) else: cmd_list.append(InputPDecrement()) else: if self.engine_type.is_FORWARD(): cmd_list.extend([InputPIncrement(), InputPDereference()]) else: cmd_list.extend([InputPDecrement(), InputPDereference()]) ta = TransitionAction(CommandList.from_iterable(cmd_list)) # NOTE: The 'from reload transition' is implemented by 'prepare_for_reload()' for source_state_index in self.__from_db[StateIndex]: assert source_state_index != E_StateIndices.NONE state.entry.enter(StateIndex, source_state_index, ta.clone()) if StateIndex == self.init_state_index: if self.engine_type.is_FORWARD(): ta = TransitionAction(CommandList(InputPDereference())) state.entry.enter_state_machine_entry(self.__state_machine_id, StateIndex, ta) return state
def group(CharacterPathList, TheAnalyzer, CompressionType): """Different character paths may be walked down by the same pathwalker, if certain conditions are met. This function groups the given list of character paths and assigns them to PathWalkerState-s. The PathWalkerState-s can then immediately be used for code generation. """ path_walker_list = [] for candidate in CharacterPathList: for path_walker in path_walker_list: # Set-up the walk in an existing PathWalkerState if path_walker.accept(candidate, TheAnalyzer.state_db): break else: # Create a new PathWalkerState path_walker_list.append( PathWalkerState(candidate, TheAnalyzer, CompressionType)) absorbance_db = defaultdict(set) for path_walker in path_walker_list: absorbance_db.update( (i, path_walker) for i in path_walker.implemented_state_index_list()) if path_walker.uniform_entry_command_list_along_all_paths is not None: # Assign the uniform command list to the transition 'path_walker -> path_walker' transition_action = TransitionAction( path_walker.index, path_walker.index, path_walker.uniform_entry_command_list_along_all_paths) # Delete transitions on the path itself => No doors for them will be implemented. path_walker.delete_transitions_on_path( ) # LEAVE THIS! This is the way to # # indicate unimportant entry doors! else: # Nothing special to be done upon iteration over the path transition_action = TransitionAction(path_walker.index, path_walker.index) transition_id = TransitionID(path_walker.index, path_walker.index) path_walker.entry.action_db[transition_id] = transition_action # Once the entries are combined, re-configure the door tree path_walker.entry.door_tree_configure() return absorbance_db
def add_mega_state(self, MegaStateIndex, StateKeyRegister, Iterable_StateKey_Index_Pairs, TheAnalyzer): """Implement a router from the MegaState-s door into the Reloader to the doors of the implemented states. Reload State .--------------------------------- - - - .--------------. on state-key reload --->| MegaState's | .---. | Reload Door |------>| 0 |-----> Reload Door of state[0] '--------------' | 1 |-----> Reload Door of state[1] | | : | : '---' '--------------------------------- - - - """ def DoorID_provider(state_index): door_id = self.entry.get_door_id(self.index, state_index) if door_id is None: # The state implemented in the MegaState did not have a # transition to 'ReloadState'. Thus, it was a total drop-out. # => Route to the state's drop-out. door_id = TheAnalyzer.drop_out_DoorID(state_index) return door_id cmd = Op.RouterOnStateKey( StateKeyRegister, MegaStateIndex, Iterable_StateKey_Index_Pairs, DoorID_provider ) ta = TransitionAction(OpList(cmd)) # Assign a DoorID (without categorization) knowing that no such entry # into this state existed before. ta.door_id = dial_db.new_door_id(self.index) assert not self.entry.has_transition(self.index, MegaStateIndex) # Cannot be in there twice! self.entry.enter(self.index, MegaStateIndex, ta) return ta.door_id
def __init__(self, StateIndex, FromStateIndexList, PreContextFulfilledID_List=None): # map: (from_state_index) --> list of actions to be taken if state is entered # 'from_state_index' for a given pre-context. # if len(FromStateIndexList) == 0: FromStateIndexList = [ E_StateIndices.NONE ] self.__state_index = StateIndex self.__action_db = dict((TransitionID(StateIndex, i), \ TransitionAction(StateIndex, i)) \ for i in FromStateIndexList) # Are the actions for all doors the same? self.__uniform_doors_f = None # Function 'categorize_command_lists()' fills the following members self.__door_db = None # map: transition_id --> door_id self.__transition_db = None # map: door_id --> transition_id self.__door_tree_root = None # The root of the door tree. # Only for 'Backward Detecting Pre-Contexts'. if PreContextFulfilledID_List is not None: pre_context_ok_command_list = [ entry_action.PreConditionOK(pre_context_id) \ for pre_context_id in PreContextFulfilledID_List ] for entry in self.__action_db.itervalues(): entry.command_list.misc.update(pre_context_ok_command_list)
def enter_OpList(self, ToStateIndex, FromStateIndex, Cl): return self.enter(ToStateIndex, FromStateIndex, TransitionAction(Cl))