Browse Source

Save action for leaving regions have to be added to each transition

benjamin.schwertfeger@gmail.com 13 years ago
parent
commit
88e2ad895b

+ 16 - 6
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/SequenceBuilder.xtend

@@ -288,12 +288,12 @@ class SequenceBuilder {
 		execState.exitSequence = seq
 	}
 
-	def StateSwitch defineExitSwitch(ExecutionScope state, Iterable<ExecutionState> leafStates, int pos) {
+	def StateSwitch defineExitSwitch(ExecutionRegion region, Iterable<ExecutionState> leafStates, int pos) {
 
 		// create a state switch
 		var StateSwitch sSwitch = sexec.factory.createStateSwitch
 		sSwitch.stateConfigurationIdx = pos
-		sSwitch.comment = "Handle exit of all possible states (of "+state.name+") at position " + sSwitch.stateConfigurationIdx + "..."
+		sSwitch.comment = "Handle exit of all possible states (of "+region.name+") at position " + sSwitch.stateConfigurationIdx + "..."
 						
 		val Iterable<ExecutionState> posStates = leafStates.filter( rs | rs.stateVector.size == 1 && rs.stateVector.offset == pos)					
 		
@@ -301,14 +301,24 @@ class SequenceBuilder {
 		for ( s : posStates ) {
 
 			val caseSeq = sexec.factory.createSequence
+
+			//Save regions if necessary
+			val exitScopes = s.parentScopes
+			exitScopes.removeAll(region.parentScopes)
+			exitScopes.remove(s)
+			exitScopes.reverse.fold(caseSeq , [ cs, exitScope | {
+				if (exitScope instanceof ExecutionRegion && (exitScope as ExecutionRegion).historyVector != null) {
+					val execRegion = exitScope as ExecutionRegion
+					cs.steps += execRegion.newSaveHistory
+				}
+				cs
+			}]) 
+
+			//Leave leaf
 			if (s.exitSequence != null) {
 				caseSeq.steps += s.exitSequence.newCall
 			}
 			
-			val exitScopes = s.parentScopes
-			exitScopes.removeAll(state.parentScopes)
-			exitScopes.remove(s)
-			
 			// include exitAction calls up to the direct child level.
 			exitScopes.fold(caseSeq , [ cs, exitScope | {
 				if (exitScope instanceof ExecutionState && s.stateVector.last == exitScope.stateVector.last) {

+ 54 - 27
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/SequenceBuilder.java

@@ -544,13 +544,13 @@ public class SequenceBuilder {
     }
   }
   
-  public StateSwitch defineExitSwitch(final ExecutionScope state, final Iterable<ExecutionState> leafStates, final int pos) {
+  public StateSwitch defineExitSwitch(final ExecutionRegion region, final Iterable<ExecutionState> leafStates, final int pos) {
     {
       SexecFactory _factory = this.sexec.factory();
       StateSwitch _createStateSwitch = _factory.createStateSwitch();
       StateSwitch sSwitch = _createStateSwitch;
       sSwitch.setStateConfigurationIdx(pos);
-      String _name = state.getName();
+      String _name = region.getName();
       String _operator_plus = StringExtensions.operator_plus("Handle exit of all possible states (of ", _name);
       String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, ") at position ");
       int _stateConfigurationIdx = sSwitch.getStateConfigurationIdx();
@@ -581,60 +581,87 @@ public class SequenceBuilder {
           SexecFactory _factory_1 = this.sexec.factory();
           Sequence _createSequence = _factory_1.createSequence();
           final Sequence caseSeq = _createSequence;
-          Sequence _exitSequence = s.getExitSequence();
-          boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_exitSequence, null);
-          if (_operator_notEquals) {
-            EList<Step> _steps = caseSeq.getSteps();
-            Sequence _exitSequence_1 = s.getExitSequence();
-            Call _newCall = this.mapping.newCall(_exitSequence_1);
-            CollectionExtensions.<Step>operator_add(_steps, _newCall);
-          }
           ArrayList<ExecutionScope> _parentScopes = this.sexec.parentScopes(s);
           final ArrayList<ExecutionScope> exitScopes = _parentScopes;
-          ArrayList<ExecutionScope> _parentScopes_1 = this.sexec.parentScopes(state);
+          ArrayList<ExecutionScope> _parentScopes_1 = this.sexec.parentScopes(region);
           exitScopes.removeAll(_parentScopes_1);
           exitScopes.remove(s);
+          List<ExecutionScope> _reverse = ListExtensions.<ExecutionScope>reverse(exitScopes);
           final Function2<Sequence,ExecutionScope,Sequence> _function_1 = new Function2<Sequence,ExecutionScope,Sequence>() {
               public Sequence apply(final Sequence cs , final ExecutionScope exitScope) {
                 Sequence _xblockexpression = null;
                 {
                   boolean _operator_and_1 = false;
-                  if (!(exitScope instanceof org.yakindu.sct.model.sexec.ExecutionState)) {
+                  if (!(exitScope instanceof org.yakindu.sct.model.sexec.ExecutionRegion)) {
                     _operator_and_1 = false;
+                  } else {
+                    StateVector _historyVector = ((ExecutionRegion) exitScope).getHistoryVector();
+                    boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_historyVector, null);
+                    _operator_and_1 = BooleanExtensions.operator_and((exitScope instanceof org.yakindu.sct.model.sexec.ExecutionRegion), _operator_notEquals);
+                  }
+                  if (_operator_and_1) {
+                    {
+                      final ExecutionRegion execRegion = ((ExecutionRegion) exitScope);
+                      EList<Step> _steps = cs.getSteps();
+                      SaveHistory _newSaveHistory = SequenceBuilder.this.sexec.newSaveHistory(execRegion);
+                      CollectionExtensions.<Step>operator_add(_steps, _newSaveHistory);
+                    }
+                  }
+                  _xblockexpression = (cs);
+                }
+                return _xblockexpression;
+              }
+            };
+          IterableExtensions.<ExecutionScope, Sequence>fold(_reverse, caseSeq, _function_1);
+          Sequence _exitSequence = s.getExitSequence();
+          boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_exitSequence, null);
+          if (_operator_notEquals_1) {
+            EList<Step> _steps_1 = caseSeq.getSteps();
+            Sequence _exitSequence_1 = s.getExitSequence();
+            Call _newCall = this.mapping.newCall(_exitSequence_1);
+            CollectionExtensions.<Step>operator_add(_steps_1, _newCall);
+          }
+          final Function2<Sequence,ExecutionScope,Sequence> _function_2 = new Function2<Sequence,ExecutionScope,Sequence>() {
+              public Sequence apply(final Sequence cs_1 , final ExecutionScope exitScope_1) {
+                Sequence _xblockexpression_1 = null;
+                {
+                  boolean _operator_and_2 = false;
+                  if (!(exitScope_1 instanceof org.yakindu.sct.model.sexec.ExecutionState)) {
+                    _operator_and_2 = false;
                   } else {
                     StateVector _stateVector_2 = s.getStateVector();
                     int _last = SequenceBuilder.this.sexec.last(_stateVector_2);
-                    StateVector _stateVector_3 = exitScope.getStateVector();
+                    StateVector _stateVector_3 = exitScope_1.getStateVector();
                     int _last_1 = SequenceBuilder.this.sexec.last(_stateVector_3);
                     boolean _operator_equals_2 = ObjectExtensions.operator_equals(((Integer)_last), ((Integer)_last_1));
-                    _operator_and_1 = BooleanExtensions.operator_and((exitScope instanceof org.yakindu.sct.model.sexec.ExecutionState), _operator_equals_2);
+                    _operator_and_2 = BooleanExtensions.operator_and((exitScope_1 instanceof org.yakindu.sct.model.sexec.ExecutionState), _operator_equals_2);
                   }
-                  if (_operator_and_1) {
+                  if (_operator_and_2) {
                     {
-                      final ExecutionState execState = ((ExecutionState) exitScope);
+                      final ExecutionState execState = ((ExecutionState) exitScope_1);
                       Step _exitAction = execState.getExitAction();
-                      boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_exitAction, null);
-                      if (_operator_notEquals_1) {
-                        EList<Step> _steps_1 = cs.getSteps();
+                      boolean _operator_notEquals_2 = ObjectExtensions.operator_notEquals(_exitAction, null);
+                      if (_operator_notEquals_2) {
+                        EList<Step> _steps_2 = cs_1.getSteps();
                         Step _exitAction_1 = execState.getExitAction();
                         Call _newCall_1 = SequenceBuilder.this.mapping.newCall(_exitAction_1);
-                        _steps_1.add(_newCall_1);
+                        _steps_2.add(_newCall_1);
                       }
                       if (SequenceBuilder.this._addTraceSteps) {
-                        EList<Step> _steps_2 = cs.getSteps();
+                        EList<Step> _steps_3 = cs_1.getSteps();
                         TraceStateExited _newTraceStateExited = SequenceBuilder.this.trace.newTraceStateExited(execState);
-                        _steps_2.add(_newTraceStateExited);
+                        _steps_3.add(_newTraceStateExited);
                       }
                     }
                   }
-                  _xblockexpression = (cs);
+                  _xblockexpression_1 = (cs_1);
                 }
-                return _xblockexpression;
+                return _xblockexpression_1;
               }
             };
-          IterableExtensions.<ExecutionScope, Sequence>fold(exitScopes, caseSeq, _function_1);
-          EList<Step> _steps_3 = caseSeq.getSteps();
-          boolean _isEmpty = _steps_3.isEmpty();
+          IterableExtensions.<ExecutionScope, Sequence>fold(exitScopes, caseSeq, _function_2);
+          EList<Step> _steps_4 = caseSeq.getSteps();
+          boolean _isEmpty = _steps_4.isEmpty();
           boolean _operator_not = BooleanExtensions.operator_not(_isEmpty);
           if (_operator_not) {
             EList<StateCase> _cases = sSwitch.getCases();

+ 42 - 5
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/Assert.java

@@ -17,6 +17,7 @@ import java.util.Set;
 import org.yakindu.sct.model.sexec.Call;
 import org.yakindu.sct.model.sexec.Execution;
 import org.yakindu.sct.model.sexec.ExecutionFlow;
+import org.yakindu.sct.model.sexec.ExecutionRegion;
 import org.yakindu.sct.model.sexec.ExecutionState;
 import org.yakindu.sct.model.sexec.ExitState;
 import org.yakindu.sct.model.sexec.HistoryEntry;
@@ -198,7 +199,7 @@ public class Assert {
 
 	public static void assertedOrder(Step step,
 			Collection<? extends ExecutionState> currentStates,
-			List<? extends StepNode> requiredSteps) {
+			List<? extends AbstractStep> requiredSteps) {
 		assertedOrder_intern(step, currentStates, requiredSteps);
 		if (!requiredSteps.isEmpty()) {
 			fail("Step was missing: " + requiredSteps.toString());
@@ -207,7 +208,7 @@ public class Assert {
 
 	private static void assertedOrder_intern(Step step,
 			Collection<? extends ExecutionState> currentStates,
-			List<? extends StepNode> requiredSteps) {
+			List<? extends AbstractStep> requiredSteps) {
 		if (requiredSteps.isEmpty()) {
 			return;
 		}
@@ -216,7 +217,7 @@ public class Assert {
 		Iterable<Step> next = null;
 		if (requiredSteps.get(0).matches(step)) {
 			found = true;
-			StepNode matched = requiredSteps.remove(0);
+			AbstractStep matched = requiredSteps.remove(0);
 			if (matched.isLeaf()) {
 				return;
 			}
@@ -236,7 +237,7 @@ public class Assert {
 
 	protected static Iterable<Step> findNext(Step step,
 			Collection<? extends ExecutionState> currentStates,
-			List<? extends StepNode> requiredSteps) {
+			List<? extends AbstractStep> requiredSteps) {
 		if (step instanceof Sequence) {
 			return ((Sequence) step).getSteps();
 		} else if (step instanceof Call) {
@@ -258,7 +259,16 @@ public class Assert {
 		return null;
 	}
 
-	public static class StepNode {
+	public abstract static class AbstractStep {
+		public abstract boolean matches(Step s);
+
+		public abstract boolean isLeaf();
+
+		public abstract Iterable<Step> next();
+
+	}
+
+	public static class StepNode extends AbstractStep {
 		public final Step step;
 		protected boolean leaf;
 
@@ -314,4 +324,31 @@ public class Assert {
 			}
 		}
 	}
+
+	public static class StepSaveHistory extends AbstractStep {
+		private final ExecutionRegion region;
+
+		public StepSaveHistory(ExecutionRegion region) {
+			this.region = region;
+		}
+
+		@Override
+		public boolean matches(Step s) {
+			if (s instanceof SaveHistory
+					&& ((SaveHistory) s).getRegion() == region) {
+				return true;
+			}
+			return false;
+		}
+
+		@Override
+		public boolean isLeaf() {
+			return true;
+		}
+
+		@Override
+		public Iterable<Step> next() {
+			return null;
+		}
+	}
 }

+ 72 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/ModelSequencerHistoryTest.java

@@ -40,6 +40,8 @@ import org.yakindu.sct.model.stext.stext.AssignmentOperator;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.VariableDefinition;
 
+import com.google.common.collect.Lists;
+
 public class ModelSequencerHistoryTest extends ModelSequencerTest {
 
 	@Test
@@ -115,4 +117,74 @@ public class ModelSequencerHistoryTest extends ModelSequencerTest {
 		assertTrue(saveStep.eClass().toString(),
 				saveStep instanceof SaveHistory);
 	}
+
+	@Test
+	public void testDeepHistorySave() {
+		Statechart sc = _createStatechart("sc");
+		{
+			InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+			VariableDefinition v1 = _createVariableDefinition("v1",
+					TYPE_INTEGER, s_scope);
+			Region r = _createRegion("r", sc);
+			{
+				Entry r_entry = _createEntry(EntryKind.DEEP_HISTORY, null, r);
+				State s1 = _createState("s1", r);
+				State s2 = _createState("s2", r);
+				{
+					_createEntryAssignment(v1, s2, 3);
+					Region r2 = _createRegion("r2", s2);
+					{
+						Entry e = _createEntry(EntryKind.INITIAL, null, r2);
+						Entry history = _createEntry(EntryKind.SHALLOW_HISTORY,
+								"history", r2);
+
+						State s3 = _createState("s3", r2);
+						{
+							_createEntryAssignment(v1, s3, 4);
+						}
+						State s4 = _createState("s4", r2);
+						{
+							Region r4 = _createRegion("r4", s4);
+							{
+								Entry e4 = _createEntry(EntryKind.INITIAL,
+										null, r2);
+								State s5 = _createState("s5", r4);
+								_createTransition(e4, s5);
+								_createTransition(s5, s1);
+							}
+						}
+						_createTransition(e, s3);
+						_createTransition(history, s3);
+						_createTransition(s3, s4);
+						_createTransition(s1, history);
+					}
+				}
+				_createTransition(r_entry, s1);
+				_createTransition(s1, s2);
+			}
+		}
+
+		ExecutionFlow flow = sequencer.transform(sc);
+
+		ExecutionState _s1 = flow.getStates().get(0);
+		assertEquals("sc.r.s1", _s1.getName());
+		ExecutionState _s2 = flow.getStates().get(1);
+		assertEquals("sc.r.s2", _s2.getName());
+		ExecutionState _s4 = flow.getStates().get(3);
+		assertEquals("sc.r.s2.r2.s4", _s4.getName());
+		ExecutionState _s5 = flow.getStates().get(4);
+		assertEquals("sc.r.s2.r2.s4.r4.s5", _s5.getName());
+
+		Step effect = _s5.getReactions().get(0).getEffect();
+
+		assertedOrder(effect, Lists.newArrayList(_s5), Lists.newArrayList(
+		//
+		// new StepSaveHistory((ExecutionRegion) _s2.getSuperScope()),//
+				new StepSaveHistory((ExecutionRegion) _s4.getSuperScope()),//
+				new StepSaveHistory((ExecutionRegion) _s5.getSuperScope()),//
+				new StepLeaf(_s5.getExitSequence().getSteps().get(0)),//
+				new StepLeaf(_s1.getEnterSequence().getSteps().get(0))//
+				));
+	}
+
 }