0+1
diff --git a/plugins/org.eclipse.qvtd.codegen/emf-gen/org/eclipse/qvtd/codegen/qvticgmodel/CGFunction.java b/plugins/org.eclipse.qvtd.codegen/emf-gen/org/eclipse/qvtd/codegen/qvticgmodel/CGFunction.java
index 9f4a4ae..f0a7a70 100644
--- a/plugins/org.eclipse.qvtd.codegen/emf-gen/org/eclipse/qvtd/codegen/qvticgmodel/CGFunction.java
+++ b/plugins/org.eclipse.qvtd.codegen/emf-gen/org/eclipse/qvtd/codegen/qvticgmodel/CGFunction.java
@@ -4,7 +4,7 @@
  * are made available under the terms of the Eclipse Public License v2.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v20.html
- * 
+ *
  * Contributors:
  *   E.D.Willink - Initial API and implementation
  *******************************************************************************/
diff --git a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaPreVisitor.java b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaPreVisitor.java
index 71c2244..e2c692a 100644
--- a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaPreVisitor.java
+++ b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaPreVisitor.java
@@ -91,7 +91,8 @@
 		JavaLocalContext<?> savedLocalContext = pushLocalContext(cgFunction);
 		try {
 			NameResolution nameResolution = getNameManager().declareStandardName(cgFunction);
-			nameResolution.addNameVariant(getCodeGenerator().getINSTANCE_NameVariant());
+			nameResolution.addNameVariant(getCodeGenerator().getCACHED_RESULT_NameVariant());
+			nameResolution.addNameVariant(getCodeGenerator().getSELF_NameVariant());
 			visitCGOperation(cgFunction);
 			return null;
 		}
diff --git a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java
index 15c286f..d0150b2 100644
--- a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java
+++ b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java
@@ -1176,7 +1176,7 @@
 		return true;
 	}
 
-	protected boolean doFunctionBody(@NonNull CGFunction cgFunction, @NonNull String instanceName) {
+	protected boolean doFunctionBody(@NonNull CGFunction cgFunction, @NonNull String cachedResultName) {
 		String functionName = getFunctionName(cgFunction);
 		CGValuedElement cgBody = cgFunction.getBody();
 		ElementId elementId = cgFunction.getTypeId().getElementId();
@@ -1187,7 +1187,7 @@
 				return false;
 			}
 			js.appendThis(functionName);
-			js.append("." + instanceName + " = ");
+			js.append("." + cachedResultName + " = ");
 			js.appendValueName(body);
 			js.append(";\n");
 		}
@@ -1221,15 +1221,15 @@
 			TypeId asTypeId = cgFunction.getASTypeId();
 			if (asTypeId == TypeId.STRING) {			// FIXME Fudge for body-less functions
 				js.appendThis(functionName);
-				js.append("." + instanceName + " = \"\";\n");
+				js.append("." + cachedResultName + " = \"\";\n");
 			}
 			else if (asTypeId == TypeId.REAL) {			// FIXME Fudge for body-less functions
 				js.appendThis(functionName);
-				js.append("." + instanceName + " = 0;\n");
+				js.append("." + cachedResultName + " = 0;\n");
 			}
 			else if (asTypeId == TypeId.INTEGER) {			// FIXME Fudge for body-less functions
 				js.appendThis(functionName);
-				js.append("." + instanceName + " = 0;\n");
+				js.append("." + cachedResultName + " = 0;\n");
 			}
 			else if (asTypeId instanceof CollectionTypeId) {			// FIXME Fudge for body-less functions
 				if (js.isUseNullAnnotations()) {
@@ -1246,17 +1246,17 @@
 				js.appendClassReference(null, Collections.class);
 				js.append("." + emptyListName + "();\n");
 				js.appendThis(functionName);
-				js.append("." + instanceName + " = " + emptyListName + ";\n");
+				js.append("." + cachedResultName + " = " + emptyListName + ";\n");
 			}
 			else {			// FIXME Fudge for body-less functions
 				js.appendThis(functionName);
-				js.append("." + instanceName + " = \"\";\n");
+				js.append("." + cachedResultName + " = \"\";\n");
 			}
 		}
 		return true;
 	}
 
-	protected boolean doFunctionBody2(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String instanceName) {
+	protected boolean doFunctionBody2(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String cachedResultName) {
 		Function function = QVTiCGUtil.getAST(cgFunction);
 		ImperativeTransformation transformation = QVTimperativeUtil.getContainingTransformation(function);
 		EntryPointsAnalysis entryPointsAnalysis = context.getEntryPointsAnalysis(transformation);
@@ -1313,7 +1313,7 @@
 		//
 		js.appendThis(functionName);
 		js.append(".");
-		js.append(instanceName);
+		js.append(cachedResultName);
 		js.append(" = ");
 		js.appendValueName(cgShadowExp);
 		js.append(";\n");
@@ -1364,8 +1364,9 @@
 		return true;
 	}
 
-	protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull String instanceName) {
+	protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull String cachedResultName) {
 		String functionName = getFunctionName(cgFunction);
+		String selfName = cgFunction.getVariantResolvedName(getCodeGenerator().getSELF_NameVariant());
 		CGClass cgClass = ClassUtil.nonNullState(CGUtil.getContainingClass(cgFunction));
 		List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgFunction.getParameters());
 		CGValuedElement cgBody = cgFunction.getBody();
@@ -1387,7 +1388,7 @@
 			js.append("\");\n");
 		}
 		js.appendThis(functionName);
-		js.append(".self = (");
+		js.append("." + selfName + " = (");
 		js.appendClassReference(cgClass);
 		js.append(")boundValues[0];\n");
 		int i = 1;
@@ -1407,12 +1408,12 @@
 			js.appendClassCast(cgParameter, castBody);
 			js.append(";\n");
 		}
-		doFunctionBody(cgFunction, instanceName);
+		doFunctionBody(cgFunction, cachedResultName);
 		js.popIndentation();
 		js.append("}\n");
 	}
 
-	protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String instanceName) {
+	protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String cachedResultName) {
 		//		List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgFunction.getParameters());
 		//		if (js.isUseNullAnnotations()) {
 		//			js.append("@SuppressWarnings(\"null\")\n");		// Accurate casts are too hard
@@ -1439,7 +1440,7 @@
 			js.append("boundValues[" + i++);
 			js.append("];\n");
 		} */
-		doFunctionBody2(cgFunction, cgShadowExp, instanceName);
+		doFunctionBody2(cgFunction, cgShadowExp, cachedResultName);
 	}
 
 	protected void doFunctionConstructorConstants(/*@NonNull*/ List<@NonNull CGOperation> cgOperations) {
@@ -1488,7 +1489,7 @@
 		}
 	} */
 
-	protected void doFunctionGetInstance(@NonNull CGFunction cgFunction, @NonNull String instanceName) {
+	protected void doFunctionGetInstance(@NonNull CGFunction cgFunction, @NonNull String cachedResultName) {
 		js.append("@Override\n");
 		js.append("public ");
 		js.appendIsRequired(false);
@@ -1496,13 +1497,14 @@
 		//		js.appendTypeDeclaration(ClassUtil.nonNullState(cgFunction.getBody()));
 		js.append(" getResult() {\n");
 		js.pushIndentation(null);
-		js.append("return " + instanceName + ";\n");
+		js.append("return " + cachedResultName + ";\n");
 		js.popIndentation();
 		js.append("}\n");
 	}
 
-	protected void doFunctionIsEqual(@NonNull CGFunction cgFunction, @NonNull String instanceName) {
+	protected void doFunctionIsEqual(@NonNull CGFunction cgFunction) {
 		String functionName = getFunctionName(cgFunction);
+		String selfName = cgFunction.getVariantResolvedName(getCodeGenerator().getSELF_NameVariant());
 		js.append("@Override\n");
 		js.append("public boolean isEqual(");
 		js.appendClassReference(true, IdResolver.class);
@@ -1514,7 +1516,7 @@
 		js.pushIndentation(null);
 		js.append("return ");
 		js.appendThis(functionName);
-		js.append(".self == thoseValues[0]");
+		js.append("." + selfName + " == thoseValues[0]");
 		int index = 1;
 		for (@NonNull CGParameter cgParameter : ClassUtil.nullFree(cgFunction.getParameters())) {
 			js.append("\n\t&& ");
@@ -2704,17 +2706,17 @@
 		return JavaStream.convertToJavaIdentifier("FTOR_" + cgFunction.getName());
 	}
 
-	protected @NonNull String getFunctionInstanceName(@NonNull CGFunction cgFunction) {
+	/*	protected @NonNull String getFunctionInstanceName(@NonNull CGFunction cgFunction) {
 		JavaLocalContext<@NonNull ?> functionContext = ClassUtil.nonNullState(qvtiGlobalContext.getLocalContext(cgFunction));
 		Object instanceKey = cgFunction.getBody();
 		if (instanceKey == null) {
 			instanceKey = QVTiCGUtil.getAST(cgFunction).getImplementationClass();
 		}
 		//	return functionContext.getNameManager().declareStandardName((CGValuedElement) instanceKey, "instance");
-		return cgFunction.getNameResolution().getVariantResolvedName(getCodeGenerator().getINSTANCE_NameVariant());
+		return cgFunction.getVariantResolvedName(getCodeGenerator().getINSTANCE_NameVariant());
 		//	nameResolution.addNameVariant(getCodeGenerator().getINSTANCE_NameVariant());
 		//	return "XXX=instance";			// XXX
-	}
+	} */
 
 	protected @NonNull String getFunctionName(@NonNull CGFunction cgFunction) {
 		return JavaStream.convertToJavaIdentifier("FUN_" + cgFunction.getName());
@@ -3084,9 +3086,8 @@
 				js.appendCommentWithOCL(null, cgFunction.getAst());
 				CGShadowExp cgShadowExp = useClassToCreateObject(cgFunction);
 				String functionName = getFunctionName(cgFunction);
+				String cachedResultName = cgFunction.getVariantResolvedName(getCodeGenerator().getCACHED_RESULT_NameVariant());
 				if (cgShadowExp != null) {
-					String instanceName = getFunctionInstanceName(cgFunction);
-					//					Type
 					js.append("protected class ");
 					js.append(functionName);
 					js.append(" extends ");
@@ -3094,17 +3095,17 @@
 					js.pushClassBody(functionName);
 					js.append("protected final ");
 					js.appendTypeDeclaration(cgFunction);
-					js.append(" " + instanceName + ";\n");
+					js.append(" " + cachedResultName + ";\n");
 					js.append("\n");
-					doFunctionConstructor(cgFunction, cgShadowExp, instanceName);
+					doFunctionConstructor(cgFunction, cgShadowExp, cachedResultName);
 					js.append("\n");
-					doFunctionGetInstance(cgFunction, instanceName);
+					doFunctionGetInstance(cgFunction, cachedResultName);
 					js.append("\n");
-					doFunctionIsEqual(cgShadowExp, instanceName);
+					doFunctionIsEqual(cgShadowExp, cachedResultName);
 					js.popClassBody(false);
 				}
 				else if (useCache(cgFunction)) {
-					String instanceName = getFunctionInstanceName(cgFunction);
+					String selfName = cgFunction.getVariantResolvedName(getCodeGenerator().getSELF_NameVariant());
 					CGClass cgClass = ClassUtil.nonNullState(CGUtil.getContainingClass(cgFunction));
 					js.append("protected class ");
 					js.append(functionName);
@@ -3115,7 +3116,7 @@
 					js.appendIsRequired(true);
 					js.append(" ");
 					js.appendClassReference(cgClass);
-					js.append(" self;\n");
+					js.append(" " + selfName + ";\n");
 					for (@NonNull CGParameter cgParameter : ClassUtil.nullFree(cgFunction.getParameters())) {
 						js.append("protected ");
 						//						js.appendDeclaration(cgParameter);
@@ -3135,13 +3136,13 @@
 					js.append("protected final ");
 					CGValuedElement cgBody = cgFunction.getBody();
 					js.appendTypeDeclaration(cgBody != null ? cgBody : cgFunction);
-					js.append(" " + instanceName + ";\n");
+					js.append(" " + cachedResultName + ";\n");
 					js.append("\n");
-					doFunctionConstructor(cgFunction, instanceName);
+					doFunctionConstructor(cgFunction, cachedResultName);
 					js.append("\n");
-					doFunctionGetInstance(cgFunction, instanceName);
+					doFunctionGetInstance(cgFunction, cachedResultName);
 					js.append("\n");
-					doFunctionIsEqual(cgFunction, instanceName);
+					doFunctionIsEqual(cgFunction);
 					js.popClassBody(false);
 				}
 				else {
@@ -3234,10 +3235,9 @@
 		js.append(")");
 		if (isIdentifiedInstance) {
 			js.append(")");
-			String instanceName = getFunctionInstanceName(cgFunction);
-			//			js.append(".getInstance()");
+			String cachedResultName = cgFunction.getVariantResolvedName(getCodeGenerator().getCACHED_RESULT_NameVariant());
 			js.append(".");
-			js.append(instanceName);
+			js.append(cachedResultName);
 		}
 		js.append(";\n");
 		return true;
diff --git a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCodeGenerator.java b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCodeGenerator.java
index 6e6a88f..1635013 100644
--- a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCodeGenerator.java
+++ b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCodeGenerator.java
@@ -207,7 +207,8 @@
 	protected final @NonNull Map<@NonNull ImperativeTransformation, @NonNull EntryPointsAnalysis> transformation2analysis = new HashMap<>();
 	private/* @LazyNonNull*/ CGPackage cgPackage;
 	private/* @LazyNonNull*/ String javaSourceCode = null;
-	protected final @NonNull NameVariant INSTANCE_NameVariant;
+	protected final @NonNull NameVariant CACHED_RESULT_NameVariant;
+	protected final @NonNull NameVariant SELF_NameVariant;
 
 	public QVTiCodeGenerator(@NonNull QVTbaseEnvironmentFactory environmentFactory, @NonNull ImperativeTransformation transformation) {
 		super(environmentFactory, null);			// FIXME Pass a genmodel
@@ -215,7 +216,8 @@
 		this.transformation = transformation;
 		this.cgAnalyzer = new QVTiAnalyzer(this);
 		this.globalContext = new QVTiGlobalContext(this);
-		this.INSTANCE_NameVariant = globalNameManager.addNameVariantPrefix("INSTANCE_");
+		this.CACHED_RESULT_NameVariant = globalNameManager.addNameVariantPreferred("cachedResult");
+		this.SELF_NameVariant = globalNameManager.addNameVariantPreferred("thisTransformer");
 	}
 
 	private void appendSegmentName(@NonNull StringBuilder s, CGPackage sPackage) {
@@ -369,6 +371,10 @@
 		return cgAnalyzer;
 	}
 
+	public @NonNull NameVariant getCACHED_RESULT_NameVariant() {
+		return CACHED_RESULT_NameVariant;
+	}
+
 	public @NonNull EntryPointsAnalysis getEntryPointsAnalysis(@NonNull ImperativeTransformation transformation) {
 		//		Map<Transformation, QVTiTransformationAnalysis> transformation2analysis = new HashMap<Transformation, QVTiTransformationAnalysis>();
 		EntryPointsAnalysis entryPointsAnalysis = transformation2analysis.get(transformation);
@@ -385,10 +391,6 @@
 		return globalContext;
 	}
 
-	public @NonNull NameVariant getINSTANCE_NameVariant() {
-		return INSTANCE_NameVariant;
-	}
-
 	@Override
 	public @NonNull QVTiCodeGenOptions getOptions() {
 		return (QVTiCodeGenOptions) super.getOptions();
@@ -406,6 +408,10 @@
 		return s.toString();
 	}
 
+	public @NonNull NameVariant getSELF_NameVariant() {
+		return SELF_NameVariant;
+	}
+
 	public @NonNull ImperativeTransformation getTransformation() {
 		return transformation;
 	}