Пример #1
0
    def report(state):
        init_tran = trans_dict[state.sig][e.Initial]
        msg = None

        get_state = lambda sig: l.get_state_by_sig(sig, flat_state_list)
        is_child = lambda sg: state in l.get_path_from_root(get_state(sg))[:-1]

        if isinstance(init_tran, e._Local):
            msg = 'cannot use LocalTransition for initial'
        elif isinstance(init_tran, e._Internal):
            msg = 'cannot use InternalTransition for initial'
        elif isinstance(init_tran, e._Choice):
            if init_tran.default is None:
                msg = ('must declare default when using Choice as initial')
            elif get_state(init_tran.default) is None:
                msg = 'default points to nonexistent state'
            elif not is_child(init_tran.default):
                msg = 'default target must be a child state'
            elif any(get_state(s) is None for s in init_tran.switch.values()):
                msg = 'switch dict references nonexistent state'
            elif not all(is_child(sig) for sig in init_tran.switch.values()):
                msg = 'switch dict value not a child state'
        # at this point we know it is instance of regular Transition
        elif init_tran.target == st.sig:
            msg = 'initial transition cannot be a loop'
        elif get_state(init_tran.target) is None:
            msg = 'transition target points to nonexistent state'
        elif not is_child(init_tran.target):
            msg = 'target state must be a child state'
        elif init_tran.guard is not e.always_true:
            msg = 'initial transition cannot have a guard'
        return (state, msg) if msg else None
Пример #2
0
 def visit(state, visited=set()):  # instantiating should be ok in this case
     if state in visited:
         return set()
     visited.add(state)
     # if orthogonal is reachable, its states are automatically reachable
     if state.kind == 'orthogonal':
         [visit(st, visited) for st in state.states]
     # all state's parents are reachable
     # visit transition targets going out of every parent state
     for parent in l.get_path_from_root(state):
         visit(parent, visited)
     # visit transition targets going out of current state
     for tran in trans_dict.get(state.sig, {}).values():
         if isinstance(tran, e._Choice):
             to_visit = [l.get_state_by_sig(sig, flat_state_list)
                         for sig in tran.switch.values() + [tran.default]]
         else:
             to_visit = [l.get_state_by_sig(tran.target, flat_state_list)]
         # nonexistent states (None values in list) are checked elsewhere
         [visit(st, visited) for st in to_visit if st is not None]
     return visited
Пример #3
0
def find_invalid_local_transitions(flat_state_list, trans_dict):
    """
        Returns list of 3-tuples (state_sig, event_type, transition).
        To be valid, local transition must be must be from superstate to
        substate or vice versa (source and target must be in parent-child
        relationship), and cannot be a self-loop.
    """
    bad_sources = find_nonexistent_transition_sources(flat_state_list,
                                                      trans_dict)
    bad_targets = find_nonexistent_transition_targets(flat_state_list,
                                                      trans_dict)
    bad_state_sigs = bad_sources + bad_targets

    get_by_sig = lambda sig: l.get_state_by_sig(sig, flat_state_list)
    common_parent = lambda sig_a, sig_b: l.get_common_parent(
        get_by_sig(sig_a), get_by_sig(sig_b)).sig

    return [(st_sig, evt, tran.target)
            for st_sig, outgoing in trans_dict.items()
            for evt, tran in outgoing.items()
            if st_sig not in bad_state_sigs and
            isinstance(tran, e._Local) and (
            st_sig == tran.target or  # loop
            common_parent(st_sig, tran.target) not in [st_sig, tran.target])]