Просмотр исходного кода

Support for choice pseudo states:
- ModelSequencer extended
- FlowOptimizer inlines choice behavior
- extended java generator

terfloth@itemis.de 14 лет назад
Родитель
Сommit
fd6f81e538

+ 6 - 2
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/templates/CustomCycleBasedStatemachine.xpt

@@ -109,7 +109,7 @@ else {
   «ENDFOREACH-»
 «ENDDEFINE»
 
-«DEFINE StatementMethodsImplement FOR ExecutionState-»
+«DEFINE StatementMethodsImplement FOR ExecutionNode-»
   «FOREACH reactions.select(e| e.effect.caller.size > 0 ) AS r-»
 	private void «r.effect.functionName()»() {
 		«EXPAND ActionCode FOR r.effect-»
@@ -117,10 +117,12 @@ else {
   «ENDFOREACH-»
 «ENDDEFINE»
 
-«DEFINE ReactMethodsImplement FOR ExecutionState-»
+«DEFINE ReactMethodsImplement FOR ExecutionNode-»
+	«IF ExecutionState.isInstance(this) || reactSequence.caller.size > 0 -»
 	private void react«getName()»() {
 		«EXPAND ActionCode FOREACH reactSequence.steps-»
 	}
+	«ENDIF -»
 «ENDDEFINE»
 
 «DEFINE EnterMethodImplement FOR ExecutionState-»
@@ -322,11 +324,13 @@ public class 
 «EXPAND ConditionMethodsImplement FOREACH this.states-»
 «EXPAND ConditionMethodsImplement FOREACH this.nodes-»
 «EXPAND StatementMethodsImplement FOREACH this.states-»
+«EXPAND StatementMethodsImplement FOREACH this.nodes-»
 «EXPAND EnterMethodImplement FOREACH this.states-»
 «EXPAND ExitMethodImplement FOREACH this.states-»
 «EXPAND EnterSequenceImplement FOREACH this.states-»
 «EXPAND ExitSequenceImplement FOREACH this.states-»
 «EXPAND ReactMethodsImplement FOREACH this.states-»
+«EXPAND ReactMethodsImplement FOREACH this.nodes-»
 	public void runCycle() {
 		«IF isTimedStatemachine()-»
 		cycleStartTime = System.currentTimeMillis();

+ 8 - 2
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/templates/Naming.ext

@@ -67,6 +67,9 @@ String getValueName(VariableDefinition this) : "var"+name.toFirstUpper();
 String getName(ExecutionState this) :
 	simpleName.replaceAll(" ","").toFirstUpper();
 	
+String getName(ExecutionNode this) :
+	simpleName.replaceAll(" ","").toFirstUpper();
+	
 String getName(ExecutionFlow this) :
 	name.replaceAll(" ","").toFirstUpper();
 
@@ -82,8 +85,9 @@ cached String functionName(Step step) :
 	(step.isEntryAction()) ? step.entryActionFunctionName() : ( 
 	(step.isExitAction()) ? step.exitActionFunctionName() :  (
 	(step.isEnterSequence()) ? step.enterSequenceName() : (
-	(step.isExitSequence()) ? step.exitSequenceName() :
-	" // unknown function type "+step )))));
+	(step.isExitSequence()) ? step.exitSequenceName() : (
+	(step.isReactSequence()) ? step.reactSequenceName() :
+	" // unknown function type "+step ))))));
  
 String statemachineEntryFunctionName(EnterState this):
 	if (this.name != null) then
@@ -101,6 +105,7 @@ String enterSequenceName(ExecutionFlow this) : "enter";
 String exitSequenceName(Step this) : "exitSequence"+getName(state()); 
 String exitSequenceName(ExecutionState this) : "exitSequence"+getName();
 String exitSequenceName(ExecutionFlow this) : "exit";
+String reactSequenceName(Step this) : "react"+getName(state()); 
 
 isEffect(Step step) : (! Check.isInstance(step)) && Reaction.isInstance(step.eContainer) ;
 isReactionCheck(Step step) : Reaction.isInstance(step.eContainer) && Check.isInstance(step);
@@ -108,6 +113,7 @@ isEntryAction(Step step) : ExecutionState.isInstance(step.eContainer) && step.st
 isExitAction(Step step) : ExecutionState.isInstance(step.eContainer) && step.state().exitAction == step;
 isEnterSequence(Step step) : Sequence.isInstance(step) && step.name == "enterSequence";
 isExitSequence(Step step) : Sequence.isInstance(step) && step.name == "exitSequence";
+isReactSequence(Step step) : Sequence.isInstance(step) && step.name == "react";
 
 Reaction reaction(Step this) : (Reaction) this.eContainer ;
 ExecutionState state(Reaction this) : (ExecutionState) eContainer;

+ 12 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/FactoryExtension.xtend

@@ -37,6 +37,8 @@ import org.yakindu.sct.model.sexec.UnscheduleTimeEvent
 import org.yakindu.sct.model.stext.stext.LocalReaction
 import org.yakindu.sct.model.sgraph.RegularState
 import org.yakindu.sct.model.sgraph.FinalState
+import org.yakindu.sct.model.sgraph.Choice
+import org.yakindu.sct.model.sexec.ExecutionChoice
 
 class FactoryExtension {
 	
@@ -69,6 +71,16 @@ class FactoryExtension {
 		}
 	}
 	
+	def ExecutionChoice create r : sexecFactory.createExecutionChoice create(Choice choice){
+		if (choice != null) {
+			val n = choice.parentRegion.vertices.filter( typeof ( Choice) ).toList.indexOf(choice)
+			r.simpleName =   "_choice" + n + "_"
+			r.name = choice.fullyQualifiedName.toString.replaceAll(" ", "")	
+			r.sourceElement = choice	
+			r.reactSequence = sexecFactory.createSequence
+		}
+	}
+	
 	def Check create r : sexecFactory.createCheck createCheck(ReactionTrigger tr){
 		r.name = tr.reaction.id
 	}

+ 15 - 9
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/FlowOptimizer.xtend

@@ -44,6 +44,9 @@ class FlowOptimizer {
 		if (_inlineEnterSequences) flow.states.forEach( state | state.enterSequence.inline )
 		if (_inlineExitSequences)  flow.states.forEach( state | state.exitSequence.inline )
 				
+		flow.nodes.forEach( node | { node.reactions.forEach( r | { r.check.inline r.effect.inline }) node })
+		flow.nodes.forEach( node | node.reactSequence.inline )
+		
 		flow
 	}
 	
@@ -62,14 +65,17 @@ class FlowOptimizer {
 	}
 	
 	def inline(Check c) {
-		val List<CheckRef> cRefs = new ArrayList<CheckRef>()
-		cRefs.addAll(c.refs)
-		
-		for ( ref : cRefs ) {
-			val clone = EcoreUtil::copy(c)
-			ref.eContainer.substitute(ref, clone)
-			ref.check = null
+		if ( c != null ) {
+			val List<CheckRef> cRefs = new ArrayList<CheckRef>()
+			cRefs.addAll(c.refs)
+			
+			for ( ref : cRefs ) {
+				val clone = EcoreUtil::copy(c)
+				ref.eContainer.substitute(ref, clone)
+				ref.check = null
+			}
 		}
+		
 		c
 	}
 	
@@ -169,8 +175,8 @@ class FlowOptimizer {
 		_copy.name = _if.name
 		_copy.comment = _if.comment
 		_copy.check =  _if.check.stepCopy as Check
-		_copy.thenStep = _if.thenStep.stepCopy
-		_copy.elseStep = _if.elseStep.stepCopy
+		_copy.thenStep = if (_if.thenStep != null ) _if.thenStep.stepCopy else null
+		_copy.elseStep = if (_if.elseStep != null ) _if.elseStep.stepCopy else null
 
 		_copy
 	}

+ 101 - 9
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/ModelSequencer.xtend

@@ -68,6 +68,10 @@ import javax.sound.sampled.BooleanControl$Type
 import org.yakindu.sct.model.sgraph.RegularState
 import org.yakindu.sct.model.sgraph.FinalState
 import org.yakindu.sct.model.sgraph.Vertex
+import org.yakindu.sct.model.sgraph.Choice
+import org.yakindu.sct.model.sexec.ExecutionChoice
+import org.yakindu.sct.model.stext.stext.DefaultEvent
+import org.yakindu.sct.model.sexec.ExecutionNode
 
 class ModelSequencer {
 	
@@ -94,7 +98,8 @@ class ModelSequencer {
 		
 		// during mapping the basic structural elements will be mapped from the source statechart to the execution flow
 		sc.mapScopes(ef)
-		sc.mapStates(ef)
+		sc.mapRegularStates(ef)
+		sc.mapPseudoStates(ef)
 		sc.mapTimeEvents(ef)
 		
 		// derive all additional information that is necessary for the execution
@@ -105,8 +110,10 @@ class ModelSequencer {
 		
 		sc.mapTransitions(ef)
 		sc.mapLocalReactions(ef)
+		sc.mapChoiceTransitions(ef)
 		
-		ef.defineStateCycles(sc)
+		ef.defineRegularStateReactions(sc)
+		ef.definePseudoStateReactions(sc)
 		
 		// retarget declaration refs
 		ef.retargetDeclRefs
@@ -158,7 +165,7 @@ class ModelSequencer {
 	 */
 
 		
-	def ExecutionFlow mapStates(Statechart statechart, ExecutionFlow r){
+	def ExecutionFlow mapRegularStates(Statechart statechart, ExecutionFlow r){
 		var content = EcoreUtil2::eAllContentsAsList(statechart)
 		val allStates = statechart.allRegularStates
 		r.states.addAll(allStates.map( s | s.mapState));
@@ -175,6 +182,23 @@ class ModelSequencer {
 	}
 	
 	
+	def ExecutionFlow mapPseudoStates(Statechart statechart, ExecutionFlow r){
+		var content = EcoreUtil2::eAllContentsAsList(statechart)
+		val allChoices = statechart.allChoices
+		r.nodes.addAll( allChoices.map( choice | choice.create ) );
+		return r
+	}
+
+
+	// TODO : move to other extension
+	def List<Choice> allChoices(Statechart sc) {
+		var content = EcoreUtil2::eAllContentsAsList(sc)
+		val allChoices = content.filter( typeof(Choice) )
+		
+		return allChoices.toList
+	}
+	
+
 	
 	def dispatch ExecutionState mapState(FinalState state) {
 		val _state = state.create
@@ -222,6 +246,20 @@ class ModelSequencer {
 	
 
 
+	def ExecutionFlow mapChoiceTransitions(Statechart statechart, ExecutionFlow r) {
+		statechart.allChoices.forEach( choice | choice.mapChoiceTransition);		
+		return r
+	}
+
+
+	def ExecutionChoice mapChoiceTransition(Choice choice) {
+		val _choice = choice.create
+		_choice.reactions.addAll( choice.outgoingTransitions.map(t | t.mapTransition) )
+		return _choice
+	}
+
+
+
 	def ExecutionFlow mapTransitions(Statechart statechart, ExecutionFlow r){
 		var content = EcoreUtil2::eAllContentsAsList(statechart)
 		val allStates = content.filter(e | e instanceof State)
@@ -237,6 +275,8 @@ class ModelSequencer {
 	}
 	 
 	 
+	 
+	 
 	def Reaction mapTransition(Transition t) {
 		val r = t.create 
 		if (t.trigger != null) r.check = mapToCheck(t.trigger)
@@ -316,10 +356,12 @@ class ModelSequencer {
 			seq
 		}])
 		
-		if (t.target != null && t.target instanceof State) {
-			sequence.steps.add((t.target as State).create.enterSequence.newCall)	
-		}
-		
+		if (t.target != null ) 
+			if ( t.target instanceof State) {
+				sequence.steps.add((t.target as State).create.enterSequence.newCall )	
+			} else if ( t.target instanceof Choice ) {
+				sequence.steps.add((t.target as Choice).create.reactSequence.newCall )	
+			}
 			
 		return sequence
 	}	
@@ -478,7 +520,7 @@ class ModelSequencer {
 	 * SEQUENCING
 	 */
 	
-	def defineStateCycles(ExecutionFlow flow, Statechart sc) {
+	def defineRegularStateReactions(ExecutionFlow flow, Statechart sc) {
 		
 		val states = sc.allRegularStates
 		
@@ -489,6 +531,48 @@ class ModelSequencer {
 	}
 	
 
+	def definePseudoStateReactions(ExecutionFlow flow, Statechart sc) {
+		
+		sc.allChoices().forEach( choice | choice.defineReaction() )
+//		val states = sc.allRegularStates
+//		
+//		states.filter(typeof(State)).filter(s | s.simple).forEach(s | defineCycle(s))
+//		states.filter(typeof(FinalState)).forEach(s | defineCycle(s))
+//		
+//		return flow
+	}
+	
+
+	def Sequence defineReaction(Choice choice) {
+	
+		val execChoice = choice.create
+		
+		// move the default transition to the end of the reaction list
+		val _default_ = execChoice.reactions.filter([ r | r.check.alwaysTrue ]).toList.head
+		if ( _default_ != null ) execChoice.reactions.move(execChoice.reactions.size -1, _default_)
+		// TODO: raise an error if no default exists 
+		
+		val stateReaction = execChoice.createReactionSequence(null)
+		execChoice.reactSequence.steps.addAll(stateReaction.steps)
+
+		execChoice.reactSequence.name = 'react'
+		execChoice.reactSequence.comment = 'The reactions of state ' + choice.name + '.'
+		
+		return execChoice.reactSequence
+	}	
+	
+
+	def alwaysTrue(Check check) {
+		if (check != null && check.condition instanceof PrimitiveValueExpression) {
+			val pve = (check.condition as PrimitiveValueExpression)
+			return ( pve.value instanceof BoolLiteral && ( pve.value as BoolLiteral ).value )
+		} 
+		
+		return false
+	}
+
+
+
 	def Sequence defineCycle(RegularState state) {
 	
 		val execState = state.create
@@ -505,7 +589,7 @@ class ModelSequencer {
 	}	
 	
 
-	def Sequence createReactionSequence(ExecutionState state, Step localStep) {	
+	def Sequence createReactionSequence(ExecutionNode state, Step localStep) {	
 		val cycle = sexecFactory.createSequence
 		
 		val localReactions = state.reactions.filter(r | ! r.transition).toList
@@ -615,6 +699,14 @@ class ModelSequencer {
 		return r
 	}
 
+	def dispatch Expression raised(DefaultEvent e) {
+		val r = stextFactory.createPrimitiveValueExpression
+		val BoolLiteral boolLit = stextFactory.createBoolLiteral
+		boolLit.value = true		
+		r.value = boolLit
+		return r
+	}
+	
 	
 	/* ==========================================================================
 	 * HANDLING TIME EVENTS

+ 58 - 10
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/FactoryExtension.java

@@ -3,28 +3,37 @@ package org.yakindu.sct.model.sexec.transformation;
 import com.google.inject.Inject;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
+import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.xtext.naming.IQualifiedNameProvider;
 import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
 import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.StringExtensions;
 import org.yakindu.sct.model.sexec.Call;
 import org.yakindu.sct.model.sexec.Check;
 import org.yakindu.sct.model.sexec.CheckRef;
+import org.yakindu.sct.model.sexec.ExecutionChoice;
 import org.yakindu.sct.model.sexec.ExecutionFlow;
 import org.yakindu.sct.model.sexec.ExecutionState;
 import org.yakindu.sct.model.sexec.ScheduleTimeEvent;
+import org.yakindu.sct.model.sexec.Sequence;
 import org.yakindu.sct.model.sexec.SexecFactory;
 import org.yakindu.sct.model.sexec.Step;
 import org.yakindu.sct.model.sexec.TimeEvent;
 import org.yakindu.sct.model.sexec.UnscheduleTimeEvent;
 import org.yakindu.sct.model.sexec.transformation.StatechartExtensions;
+import org.yakindu.sct.model.sgraph.Choice;
 import org.yakindu.sct.model.sgraph.Reaction;
+import org.yakindu.sct.model.sgraph.Region;
 import org.yakindu.sct.model.sgraph.RegularState;
 import org.yakindu.sct.model.sgraph.Scope;
 import org.yakindu.sct.model.sgraph.Statechart;
 import org.yakindu.sct.model.sgraph.Statement;
 import org.yakindu.sct.model.sgraph.Transition;
+import org.yakindu.sct.model.sgraph.Vertex;
 import org.yakindu.sct.model.stext.stext.EventDefinition;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
@@ -164,6 +173,45 @@ public class FactoryExtension {
     return r;
   }
   
+  private final HashMap<ArrayList<?>,ExecutionChoice> _createCache_create_6 = new HashMap<ArrayList<?>,ExecutionChoice>();
+  
+  public ExecutionChoice create(final Choice choice) {
+    final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(choice);
+    ExecutionChoice r;
+    synchronized (_createCache_create_6) {
+      if (_createCache_create_6.containsKey(_cacheKey)) {
+        return _createCache_create_6.get(_cacheKey);
+      }
+      SexecFactory _sexecFactory = this.sexecFactory();
+      ExecutionChoice _createExecutionChoice = _sexecFactory.createExecutionChoice();
+      r = _createExecutionChoice;
+      _createCache_create_6.put(_cacheKey, r);
+    }
+    boolean _operator_notEquals = ObjectExtensions.operator_notEquals(choice, null);
+    if (_operator_notEquals) {
+      {
+        Region _parentRegion = choice.getParentRegion();
+        EList<Vertex> _vertices = _parentRegion.getVertices();
+        Iterable<Choice> _filter = IterableExtensions.<Choice>filter(_vertices, org.yakindu.sct.model.sgraph.Choice.class);
+        List<Choice> _list = IterableExtensions.<Choice>toList(_filter);
+        int _indexOf = _list.indexOf(choice);
+        final int n = _indexOf;
+        String _operator_plus = StringExtensions.operator_plus("_choice", ((Integer)n));
+        String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, "_");
+        r.setSimpleName(_operator_plus_1);
+        QualifiedName _fullyQualifiedName = this.qfnProvider.getFullyQualifiedName(choice);
+        String _string = _fullyQualifiedName.toString();
+        String _replaceAll = _string.replaceAll(" ", "");
+        r.setName(_replaceAll);
+        r.setSourceElement(choice);
+        SexecFactory _sexecFactory_1 = this.sexecFactory();
+        Sequence _createSequence = _sexecFactory_1.createSequence();
+        r.setReactSequence(_createSequence);
+      }
+    }
+    return r;
+  }
+  
   private final HashMap<ArrayList<?>,Check> _createCache_createCheck = new HashMap<ArrayList<?>,Check>();
   
   public Check createCheck(final ReactionTrigger tr) {
@@ -184,19 +232,19 @@ public class FactoryExtension {
     return r;
   }
   
-  private final HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction> _createCache_create_6 = new HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction>();
+  private final HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction> _createCache_create_7 = new HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction>();
   
   public org.yakindu.sct.model.sexec.Reaction create(final Transition tr) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(tr);
     org.yakindu.sct.model.sexec.Reaction r;
-    synchronized (_createCache_create_6) {
-      if (_createCache_create_6.containsKey(_cacheKey)) {
-        return _createCache_create_6.get(_cacheKey);
+    synchronized (_createCache_create_7) {
+      if (_createCache_create_7.containsKey(_cacheKey)) {
+        return _createCache_create_7.get(_cacheKey);
       }
       SexecFactory _sexecFactory = this.sexecFactory();
       org.yakindu.sct.model.sexec.Reaction _createReaction = _sexecFactory.createReaction();
       r = _createReaction;
-      _createCache_create_6.put(_cacheKey, r);
+      _createCache_create_7.put(_cacheKey, r);
     }
     {
       String _id = this.sce.id(tr);
@@ -207,19 +255,19 @@ public class FactoryExtension {
     return r;
   }
   
-  private final HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction> _createCache_create_7 = new HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction>();
+  private final HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction> _createCache_create_8 = new HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction>();
   
   public org.yakindu.sct.model.sexec.Reaction create(final LocalReaction lr) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(lr);
     org.yakindu.sct.model.sexec.Reaction r;
-    synchronized (_createCache_create_7) {
-      if (_createCache_create_7.containsKey(_cacheKey)) {
-        return _createCache_create_7.get(_cacheKey);
+    synchronized (_createCache_create_8) {
+      if (_createCache_create_8.containsKey(_cacheKey)) {
+        return _createCache_create_8.get(_cacheKey);
       }
       SexecFactory _sexecFactory = this.sexecFactory();
       org.yakindu.sct.model.sexec.Reaction _createReaction = _sexecFactory.createReaction();
       r = _createReaction;
-      _createCache_create_7.put(_cacheKey, r);
+      _createCache_create_8.put(_cacheKey, r);
     }
     {
       String _id = this.sce.id(lr);

+ 71 - 14
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/FlowOptimizer.java

@@ -16,6 +16,7 @@ import org.yakindu.sct.model.sexec.Call;
 import org.yakindu.sct.model.sexec.Check;
 import org.yakindu.sct.model.sexec.CheckRef;
 import org.yakindu.sct.model.sexec.ExecutionFlow;
+import org.yakindu.sct.model.sexec.ExecutionNode;
 import org.yakindu.sct.model.sexec.ExecutionState;
 import org.yakindu.sct.model.sexec.If;
 import org.yakindu.sct.model.sexec.Reaction;
@@ -125,6 +126,41 @@ public class FlowOptimizer {
           };
         IterableExtensions.<ExecutionState>forEach(_states_3, _function_3);
       }
+      EList<ExecutionNode> _nodes = flow.getNodes();
+      final Function1<ExecutionNode,ExecutionNode> _function_4 = new Function1<ExecutionNode,ExecutionNode>() {
+          public ExecutionNode apply(final ExecutionNode node) {
+            ExecutionNode _xblockexpression_1 = null;
+            {
+              EList<Reaction> _reactions = node.getReactions();
+              final Function1<Reaction,Step> _function_5 = new Function1<Reaction,Step>() {
+                  public Step apply(final Reaction r) {
+                    Step _xblockexpression_2 = null;
+                    {
+                      Check _check = r.getCheck();
+                      FlowOptimizer.this.inline(_check);
+                      Step _effect = r.getEffect();
+                      Step _inline_4 = FlowOptimizer.this.inline(_effect);
+                      _xblockexpression_2 = (_inline_4);
+                    }
+                    return _xblockexpression_2;
+                  }
+                };
+              IterableExtensions.<Reaction>forEach(_reactions, _function_5);
+              _xblockexpression_1 = (node);
+            }
+            return _xblockexpression_1;
+          }
+        };
+      IterableExtensions.<ExecutionNode>forEach(_nodes, _function_4);
+      EList<ExecutionNode> _nodes_1 = flow.getNodes();
+      final Function1<ExecutionNode,Step> _function_6 = new Function1<ExecutionNode,Step>() {
+          public Step apply(final ExecutionNode node_1) {
+            Sequence _reactSequence = node_1.getReactSequence();
+            Step _inline_5 = FlowOptimizer.this.inline(_reactSequence);
+            return _inline_5;
+          }
+        };
+      IterableExtensions.<ExecutionNode>forEach(_nodes_1, _function_6);
       _xblockexpression = (flow);
     }
     return _xblockexpression;
@@ -169,17 +205,22 @@ public class FlowOptimizer {
   public Check inline(final Check c) {
     Check _xblockexpression = null;
     {
-      ArrayList<CheckRef> _arrayList = new ArrayList<CheckRef>();
-      final List<CheckRef> cRefs = _arrayList;
-      EList<CheckRef> _refs = c.getRefs();
-      cRefs.addAll(_refs);
-      for (CheckRef ref : cRefs) {
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(c, null);
+      if (_operator_notEquals) {
         {
-          Check _copy = EcoreUtil.<Check>copy(c);
-          final Check clone = _copy;
-          EObject _eContainer = ref.eContainer();
-          this.substitute(_eContainer, ref, clone);
-          ref.setCheck(null);
+          ArrayList<CheckRef> _arrayList = new ArrayList<CheckRef>();
+          final List<CheckRef> cRefs = _arrayList;
+          EList<CheckRef> _refs = c.getRefs();
+          cRefs.addAll(_refs);
+          for (CheckRef ref : cRefs) {
+            {
+              Check _copy = EcoreUtil.<Check>copy(c);
+              final Check clone = _copy;
+              EObject _eContainer = ref.eContainer();
+              this.substitute(_eContainer, ref, clone);
+              ref.setCheck(null);
+            }
+          }
         }
       }
       _xblockexpression = (c);
@@ -379,12 +420,28 @@ public class FlowOptimizer {
       Check _check = _if.getCheck();
       Step _stepCopy = this.stepCopy(_check);
       _copy.setCheck(((Check) _stepCopy));
+      Step _xifexpression = null;
       Step _thenStep = _if.getThenStep();
-      Step _stepCopy_1 = this.stepCopy(_thenStep);
-      _copy.setThenStep(_stepCopy_1);
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_thenStep, null);
+      if (_operator_notEquals) {
+        Step _thenStep_1 = _if.getThenStep();
+        Step _stepCopy_1 = this.stepCopy(_thenStep_1);
+        _xifexpression = _stepCopy_1;
+      } else {
+        _xifexpression = null;
+      }
+      _copy.setThenStep(_xifexpression);
+      Step _xifexpression_1 = null;
       Step _elseStep = _if.getElseStep();
-      Step _stepCopy_2 = this.stepCopy(_elseStep);
-      _copy.setElseStep(_stepCopy_2);
+      boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_elseStep, null);
+      if (_operator_notEquals_1) {
+        Step _elseStep_1 = _if.getElseStep();
+        Step _stepCopy_2 = this.stepCopy(_elseStep_1);
+        _xifexpression_1 = _stepCopy_2;
+      } else {
+        _xifexpression_1 = null;
+      }
+      _copy.setElseStep(_xifexpression_1);
       _xblockexpression = (_copy);
     }
     return _xblockexpression;

+ 194 - 18
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/ModelSequencer.java

@@ -15,6 +15,7 @@ import org.eclipse.xtext.xbase.lib.CollectionLiterals;
 import org.eclipse.xtext.xbase.lib.ComparableExtensions;
 import org.eclipse.xtext.xbase.lib.Functions.Function1;
 import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.IntegerExtensions;
 import org.eclipse.xtext.xbase.lib.IterableExtensions;
 import org.eclipse.xtext.xbase.lib.ListExtensions;
 import org.eclipse.xtext.xbase.lib.ObjectExtensions;
@@ -24,7 +25,9 @@ import org.yakindu.sct.model.sexec.Check;
 import org.yakindu.sct.model.sexec.CheckRef;
 import org.yakindu.sct.model.sexec.EnterState;
 import org.yakindu.sct.model.sexec.Execution;
+import org.yakindu.sct.model.sexec.ExecutionChoice;
 import org.yakindu.sct.model.sexec.ExecutionFlow;
+import org.yakindu.sct.model.sexec.ExecutionNode;
 import org.yakindu.sct.model.sexec.ExecutionState;
 import org.yakindu.sct.model.sexec.ExitState;
 import org.yakindu.sct.model.sexec.If;
@@ -41,6 +44,7 @@ import org.yakindu.sct.model.sexec.TimeEvent;
 import org.yakindu.sct.model.sexec.UnscheduleTimeEvent;
 import org.yakindu.sct.model.sexec.transformation.FactoryExtension;
 import org.yakindu.sct.model.sexec.transformation.StatechartExtensions;
+import org.yakindu.sct.model.sgraph.Choice;
 import org.yakindu.sct.model.sgraph.Declaration;
 import org.yakindu.sct.model.sgraph.Effect;
 import org.yakindu.sct.model.sgraph.Entry;
@@ -61,11 +65,13 @@ import org.yakindu.sct.model.sgraph.Vertex;
 import org.yakindu.sct.model.stext.stext.AlwaysEvent;
 import org.yakindu.sct.model.stext.stext.Assignment;
 import org.yakindu.sct.model.stext.stext.BoolLiteral;
+import org.yakindu.sct.model.stext.stext.DefaultEvent;
 import org.yakindu.sct.model.stext.stext.ElementReferenceExpression;
 import org.yakindu.sct.model.stext.stext.EventDefinition;
 import org.yakindu.sct.model.stext.stext.EventSpec;
 import org.yakindu.sct.model.stext.stext.Expression;
 import org.yakindu.sct.model.stext.stext.IntLiteral;
+import org.yakindu.sct.model.stext.stext.Literal;
 import org.yakindu.sct.model.stext.stext.LocalReaction;
 import org.yakindu.sct.model.stext.stext.LogicalAndExpression;
 import org.yakindu.sct.model.stext.stext.LogicalOrExpression;
@@ -106,7 +112,8 @@ public class ModelSequencer {
       ExecutionFlow _create = this.factory.create(sc);
       final ExecutionFlow ef = _create;
       this.mapScopes(sc, ef);
-      this.mapStates(sc, ef);
+      this.mapRegularStates(sc, ef);
+      this.mapPseudoStates(sc, ef);
       this.mapTimeEvents(sc, ef);
       this.defineStateVector(ef, sc);
       this.defineStateEnterSequences(ef, sc);
@@ -114,7 +121,9 @@ public class ModelSequencer {
       this.defineEnterSequence(ef, sc);
       this.mapTransitions(sc, ef);
       this.mapLocalReactions(sc, ef);
-      this.defineStateCycles(ef, sc);
+      this.mapChoiceTransitions(sc, ef);
+      this.defineRegularStateReactions(ef, sc);
+      this.definePseudoStateReactions(ef, sc);
       this.retargetDeclRefs(ef);
       return ef;
     }
@@ -183,7 +192,7 @@ public class ModelSequencer {
     }
   }
   
-  public ExecutionFlow mapStates(final Statechart statechart, final ExecutionFlow r) {
+  public ExecutionFlow mapRegularStates(final Statechart statechart, final ExecutionFlow r) {
     {
       List<EObject> _eAllContentsAsList = EcoreUtil2.eAllContentsAsList(statechart);
       List<EObject> content = _eAllContentsAsList;
@@ -213,6 +222,36 @@ public class ModelSequencer {
     }
   }
   
+  public ExecutionFlow mapPseudoStates(final Statechart statechart, final ExecutionFlow r) {
+    {
+      List<EObject> _eAllContentsAsList = EcoreUtil2.eAllContentsAsList(statechart);
+      List<EObject> content = _eAllContentsAsList;
+      List<Choice> _allChoices = this.allChoices(statechart);
+      final List<Choice> allChoices = _allChoices;
+      EList<ExecutionNode> _nodes = r.getNodes();
+      final Function1<Choice,ExecutionChoice> _function = new Function1<Choice,ExecutionChoice>() {
+          public ExecutionChoice apply(final Choice choice) {
+            ExecutionChoice _create = ModelSequencer.this.factory.create(choice);
+            return _create;
+          }
+        };
+      List<ExecutionChoice> _map = ListExtensions.<Choice, ExecutionChoice>map(allChoices, _function);
+      _nodes.addAll(_map);
+      return r;
+    }
+  }
+  
+  public List<Choice> allChoices(final Statechart sc) {
+    {
+      List<EObject> _eAllContentsAsList = EcoreUtil2.eAllContentsAsList(sc);
+      List<EObject> content = _eAllContentsAsList;
+      Iterable<Choice> _filter = IterableExtensions.<Choice>filter(content, org.yakindu.sct.model.sgraph.Choice.class);
+      final Iterable<Choice> allChoices = _filter;
+      List<Choice> _list = IterableExtensions.<Choice>toList(allChoices);
+      return _list;
+    }
+  }
+  
   protected ExecutionState _mapState(final FinalState state) {
     {
       ExecutionState _create = this.factory.create(state);
@@ -288,6 +327,38 @@ public class ModelSequencer {
     return _xblockexpression;
   }
   
+  public ExecutionFlow mapChoiceTransitions(final Statechart statechart, final ExecutionFlow r) {
+    {
+      List<Choice> _allChoices = this.allChoices(statechart);
+      final Function1<Choice,ExecutionChoice> _function = new Function1<Choice,ExecutionChoice>() {
+          public ExecutionChoice apply(final Choice choice) {
+            ExecutionChoice _mapChoiceTransition = ModelSequencer.this.mapChoiceTransition(choice);
+            return _mapChoiceTransition;
+          }
+        };
+      IterableExtensions.<Choice>forEach(_allChoices, _function);
+      return r;
+    }
+  }
+  
+  public ExecutionChoice mapChoiceTransition(final Choice choice) {
+    {
+      ExecutionChoice _create = this.factory.create(choice);
+      final ExecutionChoice _choice = _create;
+      EList<Reaction> _reactions = _choice.getReactions();
+      EList<Transition> _outgoingTransitions = choice.getOutgoingTransitions();
+      final Function1<Transition,Reaction> _function = new Function1<Transition,Reaction>() {
+          public Reaction apply(final Transition t) {
+            Reaction _mapTransition = ModelSequencer.this.mapTransition(t);
+            return _mapTransition;
+          }
+        };
+      List<Reaction> _map = ListExtensions.<Transition, Reaction>map(_outgoingTransitions, _function);
+      _reactions.addAll(_map);
+      return _choice;
+    }
+  }
+  
   public ExecutionFlow mapTransitions(final Statechart statechart, final ExecutionFlow r) {
     {
       List<EObject> _eAllContentsAsList = EcoreUtil2.eAllContentsAsList(statechart);
@@ -542,22 +613,28 @@ public class ModelSequencer {
           }
         };
       IterableExtensions.<State, Sequence>fold(_reverse, sequence, _function_1);
-      boolean _operator_and_3 = false;
       Vertex _target_1 = t.getTarget();
       boolean _operator_notEquals_6 = ObjectExtensions.operator_notEquals(_target_1, null);
-      if (!_operator_notEquals_6) {
-        _operator_and_3 = false;
-      } else {
+      if (_operator_notEquals_6) {
         Vertex _target_2 = t.getTarget();
-        _operator_and_3 = BooleanExtensions.operator_and(_operator_notEquals_6, (_target_2 instanceof org.yakindu.sct.model.sgraph.State));
-      }
-      if (_operator_and_3) {
-        EList<Step> _steps_4 = sequence.getSteps();
-        Vertex _target_3 = t.getTarget();
-        ExecutionState _create_5 = this.factory.create(((State) _target_3));
-        Sequence _enterSequence = _create_5.getEnterSequence();
-        Call _newCall_3 = this.factory.newCall(_enterSequence);
-        _steps_4.add(_newCall_3);
+        if ((_target_2 instanceof org.yakindu.sct.model.sgraph.State)) {
+          EList<Step> _steps_4 = sequence.getSteps();
+          Vertex _target_3 = t.getTarget();
+          ExecutionState _create_5 = this.factory.create(((State) _target_3));
+          Sequence _enterSequence = _create_5.getEnterSequence();
+          Call _newCall_3 = this.factory.newCall(_enterSequence);
+          _steps_4.add(_newCall_3);
+        } else {
+          Vertex _target_4 = t.getTarget();
+          if ((_target_4 instanceof org.yakindu.sct.model.sgraph.Choice)) {
+            EList<Step> _steps_5 = sequence.getSteps();
+            Vertex _target_5 = t.getTarget();
+            ExecutionChoice _create_6 = this.factory.create(((Choice) _target_5));
+            Sequence _reactSequence = _create_6.getReactSequence();
+            Call _newCall_4 = this.factory.newCall(_reactSequence);
+            _steps_5.add(_newCall_4);
+          }
+        }
       }
       return sequence;
     }
@@ -910,7 +987,7 @@ public class ModelSequencer {
     return _xblockexpression;
   }
   
-  public ExecutionFlow defineStateCycles(final ExecutionFlow flow, final Statechart sc) {
+  public ExecutionFlow defineRegularStateReactions(final ExecutionFlow flow, final Statechart sc) {
     {
       List<RegularState> _allRegularStates = this.allRegularStates(sc);
       final List<RegularState> states = _allRegularStates;
@@ -941,6 +1018,89 @@ public class ModelSequencer {
     }
   }
   
+  public void definePseudoStateReactions(final ExecutionFlow flow, final Statechart sc) {
+    List<Choice> _allChoices = this.allChoices(sc);
+    final Function1<Choice,Sequence> _function = new Function1<Choice,Sequence>() {
+        public Sequence apply(final Choice choice) {
+          Sequence _defineReaction = ModelSequencer.this.defineReaction(choice);
+          return _defineReaction;
+        }
+      };
+    IterableExtensions.<Choice>forEach(_allChoices, _function);
+  }
+  
+  public Sequence defineReaction(final Choice choice) {
+    {
+      ExecutionChoice _create = this.factory.create(choice);
+      final ExecutionChoice execChoice = _create;
+      EList<Reaction> _reactions = execChoice.getReactions();
+      final Function1<Reaction,Boolean> _function = new Function1<Reaction,Boolean>() {
+          public Boolean apply(final Reaction r) {
+            Check _check = r.getCheck();
+            boolean _alwaysTrue = ModelSequencer.this.alwaysTrue(_check);
+            return ((Boolean)_alwaysTrue);
+          }
+        };
+      Iterable<Reaction> _filter = IterableExtensions.<Reaction>filter(_reactions, _function);
+      List<Reaction> _list = IterableExtensions.<Reaction>toList(_filter);
+      Reaction _head = IterableExtensions.<Reaction>head(_list);
+      final Reaction _default_ = _head;
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_default_, null);
+      if (_operator_notEquals) {
+        EList<Reaction> _reactions_1 = execChoice.getReactions();
+        EList<Reaction> _reactions_2 = execChoice.getReactions();
+        int _size = _reactions_2.size();
+        int _operator_minus = IntegerExtensions.operator_minus(((Integer)_size), ((Integer)1));
+        _reactions_1.move(_operator_minus, _default_);
+      }
+      Sequence _createReactionSequence = this.createReactionSequence(execChoice, null);
+      final Sequence stateReaction = _createReactionSequence;
+      Sequence _reactSequence = execChoice.getReactSequence();
+      EList<Step> _steps = _reactSequence.getSteps();
+      EList<Step> _steps_1 = stateReaction.getSteps();
+      _steps.addAll(_steps_1);
+      Sequence _reactSequence_1 = execChoice.getReactSequence();
+      _reactSequence_1.setName("react");
+      Sequence _reactSequence_2 = execChoice.getReactSequence();
+      String _name = choice.getName();
+      String _operator_plus = StringExtensions.operator_plus("The reactions of state ", _name);
+      String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, ".");
+      _reactSequence_2.setComment(_operator_plus_1);
+      Sequence _reactSequence_3 = execChoice.getReactSequence();
+      return _reactSequence_3;
+    }
+  }
+  
+  public boolean alwaysTrue(final Check check) {
+    {
+      boolean _operator_and = false;
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(check, null);
+      if (!_operator_notEquals) {
+        _operator_and = false;
+      } else {
+        Statement _condition = check.getCondition();
+        _operator_and = BooleanExtensions.operator_and(_operator_notEquals, (_condition instanceof org.yakindu.sct.model.stext.stext.PrimitiveValueExpression));
+      }
+      if (_operator_and) {
+        {
+          Statement _condition_1 = check.getCondition();
+          final PrimitiveValueExpression pve = ((PrimitiveValueExpression) _condition_1);
+          boolean _operator_and_1 = false;
+          Literal _value = pve.getValue();
+          if (!(_value instanceof org.yakindu.sct.model.stext.stext.BoolLiteral)) {
+            _operator_and_1 = false;
+          } else {
+            Literal _value_1 = pve.getValue();
+            boolean _isValue = ((BoolLiteral) _value_1).isValue();
+            _operator_and_1 = BooleanExtensions.operator_and((_value instanceof org.yakindu.sct.model.stext.stext.BoolLiteral), _isValue);
+          }
+          return _operator_and_1;
+        }
+      }
+      return false;
+    }
+  }
+  
   public Sequence defineCycle(final RegularState state) {
     {
       ExecutionState _create = this.factory.create(state);
@@ -970,7 +1130,7 @@ public class ModelSequencer {
     }
   }
   
-  public Sequence createReactionSequence(final ExecutionState state, final Step localStep) {
+  public Sequence createReactionSequence(final ExecutionNode state, final Step localStep) {
     {
       SexecFactory _sexecFactory = this.sexecFactory();
       Sequence _createSequence = _sexecFactory.createSequence();
@@ -1246,6 +1406,20 @@ public class ModelSequencer {
     }
   }
   
+  protected Expression _raised(final DefaultEvent e) {
+    {
+      StextFactory _stextFactory = this.stextFactory();
+      PrimitiveValueExpression _createPrimitiveValueExpression = _stextFactory.createPrimitiveValueExpression();
+      final PrimitiveValueExpression r = _createPrimitiveValueExpression;
+      StextFactory _stextFactory_1 = this.stextFactory();
+      BoolLiteral _createBoolLiteral = _stextFactory_1.createBoolLiteral();
+      final BoolLiteral boolLit = _createBoolLiteral;
+      boolLit.setValue(true);
+      r.setValue(boolLit);
+      return r;
+    }
+  }
+  
   private final HashMap<ArrayList<?>,TimeEvent> _createCache_createDerivedEvent = new HashMap<ArrayList<?>,TimeEvent>();
   
   public TimeEvent createDerivedEvent(final TimeEventSpec tes) {
@@ -1912,6 +2086,8 @@ public class ModelSequencer {
   public Expression raised(final EventSpec e) {
     if ((e instanceof AlwaysEvent)) {
       return _raised((AlwaysEvent)e);
+    } else if ((e instanceof DefaultEvent)) {
+      return _raised((DefaultEvent)e);
     } else if ((e instanceof OnCycleEvent)) {
       return _raised((OnCycleEvent)e);
     } else if ((e instanceof RegularEventSpec)) {