Пример #1
0
    def add_state(self, *, mod: module.Module, st: state.State):
        if st in self.states:
            logging.error(f"Attempt to add state `{st.name}` twice!")
            return

        # annotate the state's signal name with it's module name
        if len(st.signal) > 0:
            st.signal = f"{mod.name}:{st.signal}"
        st.module_name = mod.name

        # make sure that all of the state's depended-upon properties exist
        for prop in st.read_props + st.write_props:
            if prop not in self.properties:
                logging.error(
                    f"Attempt to add state which depends on unknown property `{prop}`!"
                )

        # register the state's signal
        with self.states_lock:
            if st.signal:
                self.states_per_signal[st.signal] = set()
            # make sure that all of the state's depended-upon signals exist
            for clause in st.triggers:
                for signal in clause:
                    if signal in self.states_per_signal:
                        self.states_per_signal[signal].add(st)
                    else:
                        logging.error(
                            f"Attempt to add state which depends on unknown signal `{signal}`!"
                        )
            self.states.add(st)
Пример #2
0
    def __init__(self,
                 *,
                 ctx: IContext,
                 state: State,
                 spike_parents: Set[Spike] = None,
                 spike_payloads: Dict[str, Any] = None):
        self.state = state
        self.ctx = ctx
        self.properties = dict()
        self.spike_parents = spike_parents
        self.spike_payloads = spike_payloads

        # Recursively complete properties dict with children:
        for prop_parent_id in state.get_all_props_ids():
            # May have been covered by a parent before
            if prop_parent_id not in self.properties:
                prop_and_children = ctx[prop_parent_id].gather_children()
                for prop in prop_and_children:
                    # Child may have been covered by a parent before
                    if prop.id() not in self.properties:
                        self.properties[prop.id()] = PropertyWrapper(
                            prop=prop,
                            ctx=self.ctx,
                            spike_parents=self.spike_parents,
                            allow_read=prop_parent_id
                            in state.get_read_props_ids(),
                            allow_write=prop_parent_id
                            in state.get_write_props_ids(),
                            boring=self.state.boring)
Пример #3
0
def under_test(default_signal, default_read, default_write, default_triggers):
    return State(
        signal=default_signal,
        read=default_read,
        write=default_write,
        cond=default_triggers,
        action=default_action
    )
Пример #4
0
 def _complete_constraint(self, st: State):
     new_conjuncts: Set[Conjunct] = deepcopy(set(st.constraint.conjunctions()))
     for conj in st.constraint.conjunctions():
         known_signals = set()
         new_conjuncts.update(
             Conjunct(*conj_signals)
             for conj_signals in self._complete_conjunction(conj, known_signals))
         assert len(known_signals) == 0
     st.completed_constraint = Disjunct(*{conj for conj in new_conjuncts})
Пример #5
0
    def rm_state(self, *, st: State) -> None:
        """
        Remove a state from this context. Note, that any state which is constrained
         on the signal that is emitted by the deleted state will also be deleted.

        * `st`: The state to remove. An error message will be generated,
         if the state was not previously added to this context with add_state().
        """
        if st not in self._activations_per_state:
            logger.error(f"Attempt to remove unknown state `{st.name}`!")
            return
        with self._lock:
            # Remove the state's signal
            if st.signal():
                self._rm_sig(st.signal())
            # Remove state activations for the state
            self._del_state_activations(st)
            # Actually forget about the state
            del self._activations_per_state[st]
        # unregister the state's consumable dummy
        self.rm_prop(prop=st.consumable)
Пример #6
0
    def receptor_decorator(action):
        nonlocal ctx_wrap, write
        ctx = ctx_wrap.ctx
        receptor_state = State(write=write,
                               read=(),
                               signal_name=None,
                               cond=None,
                               action=action,
                               is_receptor=True)

        def receptor_function(*args, **kwargs):
            nonlocal receptor_state, ctx
            Activation(st=receptor_state, ctx=ctx).run(*args, **kwargs)

        return receptor_function
Пример #7
0
    def receptor_decorator(action):
        nonlocal ctx_wrap, write
        ctx = ctx_wrap.ctx
        receptor_state = State(write=write,
                               read=(),
                               signal=None,
                               triggers=(),
                               action=action,
                               is_receptor=True)

        def receptor_function(*args, **kwargs):
            nonlocal receptor_state, ctx
            activation = StateActivation(st=receptor_state, ctx=ctx)
            act_thread = activation.run(args, kwargs)
            act_thread.start()

        return receptor_function
Пример #8
0
    def receptor_decorator(action):
        nonlocal ctx_wrap, write
        if isinstance(ctx_wrap, ContextWrapper):
            ctx = ctx_wrap.ctx
        else:
            ctx = ctx_wrap
        receptor_state = State(write=write,
                               read=(),
                               signal=None,
                               cond=None,
                               action=action,
                               is_receptor=True)

        def receptor_function(*args, **kwargs):
            nonlocal receptor_state, ctx
            Activation(st=receptor_state, ctx=ctx).run(*args, **kwargs)

        return receptor_function
Пример #9
0
    def add_state(self, *, st: State) -> None:
        """
        Add a state to this context. It will be indexed wrt/ the properties/signals
         it depends on. Error messages will be generated for unknown signals/properties.

        * `st`: The state which should be added to this context.
        """
        if st in self._activations_per_state:
            logger.error(f"Attempt to add state `{st.name}` twice!")
            return

        # make sure that all of the state's depended-upon properties exist
        for prop in st.read_props+st.write_props:
            if prop not in self._properties:
                logger.error(f"Attempt to add state which depends on unknown property `{prop}`!")
                return

        # replace configurable ages with their config values
        for signal in st.constraint.signals():
            if isinstance(signal.min_age, ConfigurableAge):
                conf_entry = self.conf(mod=st.module_name, key=signal.min_age.key)
                if conf_entry is None:
                    logger.error(f"Could not set min_age for cond of state {st.name} in module {st.module_name}")
                    signal.min_age = 0.
                else:
                    signal.min_age = conf_entry
            if isinstance(signal.max_age, ConfigurableAge):
                conf_entry = self.conf(mod=st.module_name, key=signal.max_age.key)
                if conf_entry is None:
                    logger.error(f"Could not set max_age for cond of state {st.name} in module {st.module_name}")
                    signal.max_age = 5.
                else:
                    signal.max_age = conf_entry

        # register the state's signal
        with self._lock:
            if st.signal():
                self._add_sig(st.signal())

            # add state's constraints as causes for the written prop's :changed signals,
            #  as well as the state's own signal.
            states_to_recomplete: Set[State] = {st}
            if not st.emit_detached:
                for conj in st.constraint.conjunctions(filter_detached=True):
                    for propname in st.write_props:
                        if propname in self._properties:
                            for signal in self._properties[propname].signals():
                                self._signal_causes[signal].append(conj)
                                # Since a new cause for the property's signal is added,
                                #  it must be added to all states depending on that signal.
                                states_to_recomplete.update(self._states_for_signal(signal))
                    if st.signal():
                        self._signal_causes[st.signal()].append(conj)

            # add state to state activation map
            self._activations_per_state[st] = set()

            # make sure that all of the state's depended-upon signals exist,
            #  add a default state activation for every constraint.
            for state in states_to_recomplete:
                self._del_state_activations(state)
                self._complete_constraint(state)
                self._new_state_activation(state)

        # register the state's consumable dummy, so that it is passed
        #  to Spike and from there to CausalGroup as a consumable resource.
        if st.consumable.id() not in self._properties:
            self.add_prop(prop=st.consumable)