[498400] Eliminate LetVariableNodeRole
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractNodeRole.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractNodeRole.java
index 1298c89..f3419f7 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractNodeRole.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractNodeRole.java
@@ -112,11 +112,6 @@
 	}
 
 	@Override
-	public boolean isLet() {
-		return false;
-	}
-
-	@Override
 	public boolean isNavigable() {
 		return false;
 	}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NodeRole.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NodeRole.java
index 0af4799..7a965af 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NodeRole.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NodeRole.java
@@ -60,8 +60,6 @@
 
 	boolean isIterator();
 
-	boolean isLet();
-
 	boolean isNavigable();
 
 	boolean isNull();
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Nodes.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Nodes.java
index 1ec525f..8cd3207 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Nodes.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Nodes.java
@@ -282,97 +282,6 @@
 		}
 	}
 
-	private static final class LetVariableNodeRole extends AbstractVariableNodeRole
-	{
-		private static final @NonNull LetVariableNodeRole CONSTANT_NAVIGABLE_DATATYPE_LET = new LetVariableNodeRole(Role.Phase.CONSTANT, NavigableEnum.NAVIGABLE, ClassableEnum.DATATYPE);
-		private static final @NonNull LetVariableNodeRole CONSTANT_NAVIGABLE_CLASS_LET = new LetVariableNodeRole(Role.Phase.CONSTANT, NavigableEnum.NAVIGABLE, ClassableEnum.CLASS);
-		private static final @NonNull LetVariableNodeRole CONSTANT_UNNAVIGABLE_DATATYPE_LET = new LetVariableNodeRole(Role.Phase.CONSTANT, NavigableEnum.UNNAVIGABLE, ClassableEnum.DATATYPE);
-		private static final @NonNull LetVariableNodeRole CONSTANT_UNNAVIGABLE_CLASS_LET = new LetVariableNodeRole(Role.Phase.CONSTANT, NavigableEnum.UNNAVIGABLE, ClassableEnum.CLASS);
-		private static final @NonNull LetVariableNodeRole LOADED_NAVIGABLE_DATATYPE_LET = new LetVariableNodeRole(Role.Phase.LOADED, NavigableEnum.NAVIGABLE, ClassableEnum.DATATYPE);
-		private static final @NonNull LetVariableNodeRole LOADED_NAVIGABLE_CLASS_LET = new LetVariableNodeRole(Role.Phase.LOADED, NavigableEnum.NAVIGABLE, ClassableEnum.CLASS);
-		private static final @NonNull LetVariableNodeRole LOADED_UNNAVIGABLE_DATATYPE_LET = new LetVariableNodeRole(Role.Phase.LOADED, NavigableEnum.UNNAVIGABLE, ClassableEnum.DATATYPE);
-		private static final @NonNull LetVariableNodeRole LOADED_UNNAVIGABLE_CLASS_LET = new LetVariableNodeRole(Role.Phase.LOADED, NavigableEnum.UNNAVIGABLE, ClassableEnum.CLASS);
-		private static final @NonNull LetVariableNodeRole PREDICATED_NAVIGABLE_DATATYPE_LET = new LetVariableNodeRole(Role.Phase.PREDICATED, NavigableEnum.NAVIGABLE, ClassableEnum.DATATYPE);
-		private static final @NonNull LetVariableNodeRole PREDICATED_NAVIGABLE_CLASS_LET = new LetVariableNodeRole(Role.Phase.PREDICATED, NavigableEnum.NAVIGABLE, ClassableEnum.CLASS);
-		private static final @NonNull LetVariableNodeRole PREDICATED_UNNAVIGABLE_DATATYPE_LET = new LetVariableNodeRole(Role.Phase.PREDICATED, NavigableEnum.UNNAVIGABLE, ClassableEnum.DATATYPE);
-		private static final @NonNull LetVariableNodeRole PREDICATED_UNNAVIGABLE_CLASS_LET = new LetVariableNodeRole(Role.Phase.PREDICATED, NavigableEnum.UNNAVIGABLE, ClassableEnum.CLASS);
-
-		public static @NonNull LetVariableNodeRole getLetVariableNodeRole(@NonNull Phase phase, @NonNull NavigableEnum navigable, @NonNull ClassableEnum classable) {
-			switch (navigable) {
-				case NAVIGABLE: {
-					switch (classable) {
-						case CLASS: {
-							switch (phase) {
-								case CONSTANT: return CONSTANT_NAVIGABLE_CLASS_LET;
-								case LOADED: return LOADED_NAVIGABLE_CLASS_LET;
-								case PREDICATED: return PREDICATED_NAVIGABLE_CLASS_LET;
-							}
-							break;
-						}
-						case DATATYPE: {
-							switch (phase) {
-								case CONSTANT: return CONSTANT_NAVIGABLE_DATATYPE_LET;
-								case LOADED: return LOADED_NAVIGABLE_DATATYPE_LET;
-								case PREDICATED: return PREDICATED_NAVIGABLE_DATATYPE_LET;
-							}
-							break;
-						}
-					}
-					break;
-				}
-				case UNNAVIGABLE: {
-					switch (classable) {
-						case CLASS: {
-							switch (phase) {
-								case CONSTANT: return CONSTANT_UNNAVIGABLE_CLASS_LET;
-								case LOADED: return LOADED_UNNAVIGABLE_CLASS_LET;
-								case PREDICATED: return PREDICATED_UNNAVIGABLE_CLASS_LET;
-							}
-							break;
-						}
-						case DATATYPE: {
-							switch (phase) {
-								case CONSTANT: return CONSTANT_UNNAVIGABLE_DATATYPE_LET;
-								case LOADED: return LOADED_UNNAVIGABLE_DATATYPE_LET;
-								case PREDICATED: return PREDICATED_UNNAVIGABLE_DATATYPE_LET;
-							}
-							break;
-						}
-					}
-					break;
-				}
-			}
-			throw new UnsupportedOperationException();
-		}
-
-		private @NonNull NavigableEnum navigable;
-
-		protected LetVariableNodeRole(@NonNull Phase phase, @NonNull NavigableEnum navigable, @NonNull ClassableEnum classable) {
-			super(phase, classable);
-			this.navigable = navigable;
-		}
-
-		@Override
-		public @NonNull LetVariableNodeRole asPhase(@NonNull Phase phase) {
-			return getLetVariableNodeRole(phase, navigable, classable);
-		}
-
-		@Override
-		public boolean isLet() {
-			return true;
-		}
-
-		@Override
-		public boolean isNavigable() {
-			return navigable == NavigableEnum.NAVIGABLE;
-		}
-
-		@Override
-		public String toString() {
-			return phase + (isNavigable() ? "-Navigable-" : "-Unnavigable-") + (isClass() ? "Class-" : "DataType-") + getClass().getSimpleName();
-		}
-	}
-
 	private static class NullNodeRole extends AbstractSimpleNodeRole
 	{
 		private static final @NonNull NullNodeRole NULL = new NullNodeRole();
@@ -874,8 +783,8 @@
 	public static @NonNull VariableNode createLetVariableNode(@NonNull Variable letVariable, @NonNull Node inNode) {
 		ClassableEnum classable = asClassable(!(letVariable.getType() instanceof DataType));
 		NavigableEnum resolvedIsNavigable = asNavigable(inNode.isNavigable());
-		LetVariableNodeRole nodeRole = LetVariableNodeRole.getLetVariableNodeRole(inNode.getNodeRole().getPhase(), resolvedIsNavigable, classable);
-		return nodeRole.createNode(inNode.getRegion(), letVariable);
+		PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(inNode.getNodeRole().getPhase(), classable, resolvedIsNavigable, GuardableEnum.STEP);
+		return patternNodeRole.createNode(inNode.getRegion(), letVariable);
 	}
 
 	public static @NonNull VariableNode createLoadedStepNode(@NonNull Region region, @NonNull VariableDeclaration stepVariable) {
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/QVTp2QVTs.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/QVTp2QVTs.java
index e73bc39..7016755 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/QVTp2QVTs.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/QVTp2QVTs.java
@@ -213,9 +213,6 @@
 		if (!nodeRole.isClass()) {
 			return false;
 		}
-		if (nodeRole.isLet()) {
-			return true;
-		}
 		if (nodeRole.isNull()) {
 			return true;
 		}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Region.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Region.java
index 9971d5f..30e5d95 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Region.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Region.java
@@ -86,7 +86,6 @@
 	 * Return the Guard nodes of the region (GuardVariable or Composing)
 	 */
 	@NonNull Iterable<@NonNull Node> getGuardNodes();
-	//	@NonNull List<@NonNull NodeConnection> getHeadConnections();
 	@NonNull List<@NonNull Node> getHeadNodes();
 	@NonNull Iterable<@NonNull DatumConnection> getIncomingConnections();
 	@NonNull Iterable<@NonNull NodeConnection> getIncomingPassedConnections();
@@ -136,7 +135,6 @@
 	@NonNull Iterable<@NonNull NodeConnection> getOutgoingUsedConnections();
 	@NonNull Iterable<@NonNull Node> getPatternNodes();
 	@NonNull Iterable<@NonNull NavigationEdge> getPredicatedNavigationEdges();
-	//	@NonNull Iterable<@NonNull Node> getPredicatedOrSpeculatedNodes();
 	@NonNull Iterable<@NonNull Edge> getRealizedEdges();
 	@NonNull Iterable<@NonNull NavigationEdge> getRealizedNavigationEdges();
 	@NonNull Iterable<@NonNull Edge> getRecursionEdges();
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/CyclicScheduledRegion2Mapping.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/CyclicScheduledRegion2Mapping.java
index 57b4c68..11621a6 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/CyclicScheduledRegion2Mapping.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/CyclicScheduledRegion2Mapping.java
@@ -57,7 +57,7 @@
 		 * The recursing type.
 		 */
 		private final @NonNull ClassDatumAnalysis classDatumAnalysis;
-		
+
 		/**
 		 * A distinctive number for distinctive auto-generated per-recursion names.
 		 */
@@ -101,35 +101,35 @@
 			org.eclipse.ocl.pivot.Class elementType = classDatumAnalysis.getCompleteClass().getPrimaryClass();
 			guardVariable = PivotUtil.createVariable(getSafeName(headNode), elementType, false, null);
 			guardPattern.getVariable().add(guardVariable);
-			
+
 			Iterable<@NonNull NodeConnection> outgoingConnections = headNode.getOutgoingPassedConnections();
 			assert Iterables.size(outgoingConnections) == 1;
 			NodeConnection outgoingConnection = Iterables.get(outgoingConnections, 0);
-//			Class elementType = classDatumAnalysis.getCompleteClass().getPrimaryClass();
-//			Variable variable = PivotUtil.createVariable(getSafeName(headNode), elementType, false, null);
-//			guardPattern.getVariable().add(variable);
-//			Variable oldVariable = classDatumAnalysis2headVariable.put(classDatumAnalysis, variable);
-//			assert oldVariable == null;
+			//			Class elementType = classDatumAnalysis.getCompleteClass().getPrimaryClass();
+			//			Variable variable = PivotUtil.createVariable(getSafeName(headNode), elementType, false, null);
+			//			guardPattern.getVariable().add(variable);
+			//			Variable oldVariable = classDatumAnalysis2headVariable.put(classDatumAnalysis, variable);
+			//			assert oldVariable == null;
 			NodeConnection incomingConnection = headNode.getIncomingPassedConnection();
 			assert incomingConnection != null;
 			connection2variable.put(incomingConnection, guardVariable);
 			//
 			//	Create the local accumulation variable.
 			//
-//				Iterable<@NonNull NodeConnection> internallyPassedConnections = headNode.getOutgoingPassedConnections();
-//				assert Iterables.size(internallyPassedConnections) == 1;
-//				ClassDatumAnalysis incomingClassDatumAnalysis = incomingConnection.getClassDatumAnalysis();
-//				NodeConnection internallyPassedConnection = Iterables.get(internallyPassedConnections, 0);
-//				ClassDatumAnalysis outgoingClassDatumAnalysis = internallyPassedConnection.getClassDatumAnalysis();
-//				if ((outgoingClassDatumAnalysis == incomingClassDatumAnalysis)
-//				 && !incoming2outgoing.values().contains(internallyPassedConnection)) {	// Multiple should not occur, but line them up pair-wise
-//					incoming2outgoing.put(incomingConnection, internallyPassedConnection);
+			//				Iterable<@NonNull NodeConnection> internallyPassedConnections = headNode.getOutgoingPassedConnections();
+			//				assert Iterables.size(internallyPassedConnections) == 1;
+			//				ClassDatumAnalysis incomingClassDatumAnalysis = incomingConnection.getClassDatumAnalysis();
+			//				NodeConnection internallyPassedConnection = Iterables.get(internallyPassedConnections, 0);
+			//				ClassDatumAnalysis outgoingClassDatumAnalysis = internallyPassedConnection.getClassDatumAnalysis();
+			//				if ((outgoingClassDatumAnalysis == incomingClassDatumAnalysis)
+			//				 && !incoming2outgoing.values().contains(internallyPassedConnection)) {	// Multiple should not occur, but line them up pair-wise
+			//					incoming2outgoing.put(incomingConnection, internallyPassedConnection);
 			Type asType = getConnectionSourcesType(incomingConnection);
 			String localName = "«local" + (index > 0 ? Integer.toString(index) : "") + "»";
 			localVariable = helper.createConnectionVariable(localName, asType, null);
 			mapping.getBottomPattern().getVariable().add(localVariable);
 			connection2variable.put(outgoingConnection, localVariable);
-	//
+			//
 			if ((asType instanceof CollectionType) && ((CollectionType)asType).isUnique()) {
 				String newName = "«new" + (index > 0 ? Integer.toString(index) : "") + "»";
 				ConnectionVariable newVariable2 = newVariable = helper.createConnectionVariable(newName, asType, null);
@@ -169,7 +169,7 @@
 		public void setAccumulatedConnection(@NonNull NodeConnection accumulatedConnection) {
 			this.accumulatedConnection = accumulatedConnection;
 			//
-			//	Select a/the outgoing recursive intermediate connection. 
+			//	Select a/the outgoing recursive intermediate connection.
 			//
 			NodeConnection intermediateConnection = accumulatedConnection;
 			ConnectionVariable accumulatedVariable2 = accumulatedVariable = createConnectionVariable(intermediateConnection);
@@ -177,14 +177,14 @@
 			connection2variable.put(intermediateConnection, accumulatedVariable2);
 		}
 	}
-	
+
 	/**
 	 * The recursions.
 	 */
 	private final @NonNull Map<@NonNull ClassDatumAnalysis, @NonNull RecursionContext> classDatumAnalysis2recursion = new HashMap<@NonNull ClassDatumAnalysis, @NonNull RecursionContext>();
 
 	/**
-	 * True if all recursions use Set accumulators allowing the unqiueness to be determined by excliusion rather than 
+	 * True if all recursions use Set accumulators allowing the unqiueness to be determined by excliusion rather than
 	 * by re-invocation suppression.
 	 */
 	private boolean allRecursionsAreUnique = false;
@@ -252,7 +252,7 @@
 	@Override
 	protected @NonNull OCLExpression createSelectByKind(@NonNull Node resultNode) {
 		throw new UnsupportedOperationException();
-/*		Variable resultVariable = classDatumAnalysis2headVariable.get(resultNode.getClassDatumAnalysis());
+		/*		Variable resultVariable = classDatumAnalysis2headVariable.get(resultNode.getClassDatumAnalysis());
 		if (resultVariable == null) {
 			OCLExpression asSource = createNullLiteralExp(); //PivotUtil.createVariableExp(getChildrenVariable());
 			CompleteClass sourceCompleteClass = resultNode.getCompleteClass();
@@ -287,11 +287,11 @@
 				RecursionContext recursion = classDatumAnalysis2recursion.get(intermediateConnection.getClassDatumAnalysis());
 				if (recursion != null) {
 					Variable callingLocalVariable = recursion.getLocalVariable();
-//					NodeConnection tailConnection = recursion.getAccumulatedConnection();
-//					if (tailConnection != null) {
-						Variable calledTailVariable = calledRegion2Mapping.getConnectionVariable(intermediateConnection);
-						guardVariable2expression.put(calledTailVariable, PivotUtil.createVariableExp(callingLocalVariable));
-//					}
+					//					NodeConnection tailConnection = recursion.getAccumulatedConnection();
+					//					if (tailConnection != null) {
+					Variable calledTailVariable = calledRegion2Mapping.getConnectionVariable(intermediateConnection);
+					guardVariable2expression.put(calledTailVariable, PivotUtil.createVariableExp(callingLocalVariable));
+					//					}
 				}
 			}
 			mappingStatement = createCall(mappingStatement, callableRegion, guardVariable2expression);
@@ -313,8 +313,8 @@
 					OperationCallExp excludingAllCallExp = PivotUtil.createOperationCallExp(localVariableExp, operation, resultVariableExp);
 					excludingAllCallExp.setType(localVariableExp.getType());
 					excludingAllCallExp.setIsRequired(localVariableExp.isIsRequired());
-					
-					
+
+
 					ConnectionStatement connectionStatement1 = QVTimperativeFactory.eINSTANCE.createConnectionStatement();
 					connectionStatement1.setTargetVariable(newVariable);
 					connectionStatement1.setValue(excludingAllCallExp);