|
|
@@ -24,6 +24,9 @@ import org.yakindu.sct.model.sgen.GeneratorEntry
|
|
|
import org.yakindu.sct.model.stext.stext.EventDefinition
|
|
|
import org.yakindu.sct.model.stext.stext.InterfaceScope
|
|
|
import org.yakindu.sct.model.stext.stext.VariableDefinition
|
|
|
+import org.yakindu.sct.model.sexec.ExecutionState
|
|
|
+import org.yakindu.sct.model.sgraph.FinalState
|
|
|
+import java.util.ArrayList
|
|
|
|
|
|
class Statemachine {
|
|
|
|
|
|
@@ -59,6 +62,10 @@ class Statemachine {
|
|
|
|
|
|
«flow.exitFunction»
|
|
|
|
|
|
+ «flow.activeFunction»
|
|
|
+
|
|
|
+ «flow.finalFunction»
|
|
|
+
|
|
|
«flow.clearInEventsFunction»
|
|
|
|
|
|
«flow.clearOutEventsFunction»
|
|
|
@@ -230,6 +237,105 @@ class Statemachine {
|
|
|
}
|
|
|
'''
|
|
|
|
|
|
+ def protected isActiveFunction(ExecutionFlow flow) '''
|
|
|
+ /**
|
|
|
+ * @see IStatemachine#isActive()
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean isActive(){
|
|
|
+
|
|
|
+ return
|
|
|
+ «FOR i : 0 ..< flow.stateVector.size SEPARATOR '||'»
|
|
|
+ stateVector[«i»] != State.«nullStateName»
|
|
|
+ «ENDFOR»;
|
|
|
+ }
|
|
|
+ '''
|
|
|
+
|
|
|
+ def protected isFinalFunction(ExecutionFlow flow) {
|
|
|
+ val finalStateImpactVector = flow.finalStateImpactVector
|
|
|
+
|
|
|
+ '''
|
|
|
+ /**
|
|
|
+ «IF !finalStateImpactVector.isCompletelyCovered»
|
|
|
+ * Always returns 'false' since this state machine can never become final.
|
|
|
+ *
|
|
|
+ «ENDIF»
|
|
|
+ * @see IStatemachine#isFinal()
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean isFinal(){
|
|
|
+ ''' +
|
|
|
+
|
|
|
+ // only if the impact vector is completely covered by final states the state machine
|
|
|
+ // can become final
|
|
|
+ {if (flow.finalStateImpactVector.isCompletelyCovered) {'''
|
|
|
+ return «FOR i : 0 ..<finalStateImpactVector.size SEPARATOR ' && '»
|
|
|
+ («FOR fs : finalStateImpactVector.get(i) SEPARATOR ' || '»
|
|
|
+ stateVector[«i»] == «
|
|
|
+ IF fs.stateVector.offset == i
|
|
|
+ »State.«fs.stateName.asEscapedIdentifier»«
|
|
|
+ ELSE
|
|
|
+ »State.«nullStateName»«
|
|
|
+ ENDIF»«
|
|
|
+ ENDFOR»)
|
|
|
+ «ENDFOR»;
|
|
|
+ '''} else {'''
|
|
|
+ return false;
|
|
|
+ '''} }
|
|
|
+
|
|
|
+ + '''}'''
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This function calculates the final state impact vector.
|
|
|
+ * This vector is an array of the size of the state machines state vector.
|
|
|
+ * Each array slot holds a List of ExecutionState instances that map to FinalState elements
|
|
|
+ * in the orginal model. The assignment of a final state to a slot means that if this state is
|
|
|
+ * active it has impact on the vector slot. Here two cases have to be distinguished:
|
|
|
+ *
|
|
|
+ * 1. The final state is directly assigned to the slot (the states vector offset). If the state is active
|
|
|
+ * then the slot will contain a reference to this state
|
|
|
+ * 2. If the parent region contains orthogonal states then all other vector positions covered by the region
|
|
|
+ * are empty (refer to no state) if the state is active so there is an indirect impact on the vector.
|
|
|
+ *
|
|
|
+ * TODO: move to sexec package/utils
|
|
|
+ */
|
|
|
+ def protected List<ExecutionState>[] finalStateImpactVector(ExecutionFlow flow) {
|
|
|
+
|
|
|
+ // we use a vector of list of states to mark which final state has impact on the different slots.
|
|
|
+ val List<ExecutionState>[] vector = newArrayOfSize(flow.stateVector.size)
|
|
|
+
|
|
|
+ // process all final states and mark all vector positions with the states
|
|
|
+ flow.states.filter[s | s.sourceElement instanceof FinalState].forEach[ fs |
|
|
|
+ // the state vector of the final states region is relevant since the final state has impact on its
|
|
|
+ // own vector position and all other positions covered by the region.
|
|
|
+ // > if a final state is active then all other positions must contain the null state.
|
|
|
+ var regionVector = fs.superScope.stateVector
|
|
|
+ for ( i : regionVector.offset ..< regionVector.offset + regionVector.size) {
|
|
|
+ // create a list for the slot if it does not already exist.
|
|
|
+ if (vector.get(i) == null) {
|
|
|
+ vector.set(i, new ArrayList<ExecutionState>())
|
|
|
+ }
|
|
|
+ // and add the final state to it.
|
|
|
+ vector.get(i).add(fs);
|
|
|
+ // so all vector positions are marked with all those final states that have impact on the slot.
|
|
|
+ }
|
|
|
+ ]
|
|
|
+
|
|
|
+ return vector
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Checks if all state vector positions are covered by states.
|
|
|
+ *
|
|
|
+ * TODO: move
|
|
|
+ */
|
|
|
+ def protected boolean isCompletelyCovered(List<ExecutionState>[] finalStateImpactVector) {
|
|
|
+ finalStateImpactVector.forall[ l | (l != null) && (!l.isEmpty) ]
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
def protected timingFunctions(ExecutionFlow flow) '''
|
|
|
«IF flow.timed»
|
|
|
/**
|