/*******************************************************************************
 * Copyright (c) 2007, 2015 Borland Software Corporation and others
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *   
 * Contributors:
 *     Borland Software Corporation - initial API and implementation
 *     Christopher Gerking - bugs 302594, 309762, 310991, 325192, 377882, 388325, 
 *     							  392080, 392153, 394498, 397215, 397218, 269744, 
 *     							  415660, 415315, 414642, 427237, 428618, 425069
 *     Alex Paperno - bugs 294127, 416584, 419299, 267917, 420970, 424584
 *     Christine Gerpheide - bugs 432969
 *******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.evaluator;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.m2m.internal.qvt.oml.NLS;
import org.eclipse.m2m.internal.qvt.oml.QvtPlugin;
import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTBindingHelper;
import org.eclipse.m2m.internal.qvt.oml.ast.binding.IModuleSourceInfo;
import org.eclipse.m2m.internal.qvt.oml.ast.env.IVirtualOperationTable;
import org.eclipse.m2m.internal.qvt.oml.ast.env.InternalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.ModelParameterExtent;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtEvaluationResult;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnvFactory;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalModuleEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalStdLibrary;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.ConstructorOperationAdapter;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.IntermediateClassFactory;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.IntermediateClassFactory.ExceptionClassInstance;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalParserUtil;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalUtil;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxRegistry;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil;
import org.eclipse.m2m.internal.qvt.oml.evaluator.TransformationInstance.InternalTransformation;
import org.eclipse.m2m.internal.qvt.oml.evaluator.iterators.QvtIterationTemplateCollectSelect;
import org.eclipse.m2m.internal.qvt.oml.evaluator.iterators.QvtIterationTemplateForExp;
import org.eclipse.m2m.internal.qvt.oml.evaluator.iterators.QvtIterationTemplateXCollect;
import org.eclipse.m2m.internal.qvt.oml.evaluator.iterators.QvtIterationTemplateXSelect;
import org.eclipse.m2m.internal.qvt.oml.expressions.Constructor;
import org.eclipse.m2m.internal.qvt.oml.expressions.ConstructorBody;
import org.eclipse.m2m.internal.qvt.oml.expressions.ContextualProperty;
import org.eclipse.m2m.internal.qvt.oml.expressions.DirectionKind;
import org.eclipse.m2m.internal.qvt.oml.expressions.EntryOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsPackage;
import org.eclipse.m2m.internal.qvt.oml.expressions.Helper;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeCallExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Library;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingBody;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingCallExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModelParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModelType;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModuleImport;
import org.eclipse.m2m.internal.qvt.oml.expressions.ObjectExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.OperationBody;
import org.eclipse.m2m.internal.qvt.oml.expressions.OperationalTransformation;
import org.eclipse.m2m.internal.qvt.oml.expressions.ResolveExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.ResolveInExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.VarParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.impl.ImperativeOperationImpl;
import org.eclipse.m2m.internal.qvt.oml.expressions.impl.OperationBodyImpl;
import org.eclipse.m2m.internal.qvt.oml.library.Context;
import org.eclipse.m2m.internal.qvt.oml.library.EObjectEStructuralFeaturePair;
import org.eclipse.m2m.internal.qvt.oml.library.LateResolveInTask;
import org.eclipse.m2m.internal.qvt.oml.library.LateResolveTask;
import org.eclipse.m2m.internal.qvt.oml.library.QvtResolveUtil;
import org.eclipse.m2m.internal.qvt.oml.stdlib.CallHandler;
import org.eclipse.m2m.internal.qvt.oml.stdlib.ConversionUtils;
import org.eclipse.m2m.internal.qvt.oml.stdlib.DictionaryImpl;
import org.eclipse.m2m.internal.qvt.oml.stdlib.MutableListImpl;
import org.eclipse.m2m.internal.qvt.oml.stdlib.model.ExceptionInstance;
import org.eclipse.m2m.internal.qvt.oml.trace.Trace;
import org.eclipse.m2m.internal.qvt.oml.trace.TraceRecord;
import org.eclipse.m2m.qvt.oml.blackbox.java.JavaModelExtent;
import org.eclipse.m2m.qvt.oml.blackbox.java.JavaModelInstance;
import org.eclipse.m2m.qvt.oml.blackbox.java.JavaModelType;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.AltExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.AssertExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.AssignExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.BlockExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.BreakExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.CatchExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ComputeExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ContinueExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.DictLiteralExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.DictLiteralPart;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ForExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ImperativeIterateExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ImperativeLoopExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.InstantiationExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ListType;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.LogExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.OrderedTupleLiteralExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.OrderedTupleLiteralPart;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.RaiseExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ReturnExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.SeverityKind;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.SwitchExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.TryExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.UnlinkExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.UnpackExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.VariableInitExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.WhileExp;
import org.eclipse.m2m.qvt.oml.util.Dictionary;
import org.eclipse.m2m.qvt.oml.util.IContext;
import org.eclipse.m2m.qvt.oml.util.Log;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.EnvironmentFactory;
import org.eclipse.ocl.EvaluationEnvironment;
import org.eclipse.ocl.EvaluationVisitor;
import org.eclipse.ocl.EvaluationVisitorImpl;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.ecore.CallOperationAction;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.EcoreFactory;
import org.eclipse.ocl.ecore.SendSignalAction;
import org.eclipse.ocl.expressions.CollectionItem;
import org.eclipse.ocl.expressions.CollectionLiteralExp;
import org.eclipse.ocl.expressions.CollectionLiteralPart;
import org.eclipse.ocl.expressions.CollectionRange;
import org.eclipse.ocl.expressions.EnumLiteralExp;
import org.eclipse.ocl.expressions.IfExp;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.expressions.OperationCallExp;
import org.eclipse.ocl.expressions.PropertyCallExp;
import org.eclipse.ocl.expressions.Variable;
import org.eclipse.ocl.expressions.VariableExp;
import org.eclipse.ocl.types.BagType;
import org.eclipse.ocl.types.CollectionType;
import org.eclipse.ocl.types.SetType;
import org.eclipse.ocl.types.TupleType;
import org.eclipse.ocl.types.VoidType;
import org.eclipse.ocl.util.CollectionUtil;
import org.eclipse.ocl.util.Tuple;
import org.eclipse.ocl.utilities.PredefinedType;
import org.eclipse.ocl.utilities.UMLReflection;


public class QvtOperationalEvaluationVisitorImpl
	extends EvaluationVisitorImpl<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject>
implements QvtOperationalEvaluationVisitor, InternalEvaluator, DeferredAssignmentListener {	

	private static int tempCounter = 0;
	
    private boolean myIsSuppressLoggin = false;

    private QvtOperationalEvaluationEnv myEvalEnv;
    // FIXME - move me to the root environment?
    private OCLAnnotationSupport oclAnnotationSupport;
    
    public QvtOperationalEvaluationVisitorImpl(QvtOperationalEnv env, QvtOperationalEvaluationEnv evalEnv) {
        super(env, evalEnv, evalEnv.createExtentMap(null));

        myEvalEnv = evalEnv;
    }
    
	protected QvtOperationalEvaluationVisitorImpl(QvtOperationalEvaluationVisitorImpl parent, QvtOperationalEvaluationEnv nestedEvalEnv) {
		this(parent.getOperationalEnv(), nestedEvalEnv);
		
		oclAnnotationSupport = parent.getOCLAnnotationSupport();
	}    
    
	protected InternalEvaluator createNestedEvaluationVisitor(QvtOperationalEvaluationVisitorImpl parent, QvtOperationalEvaluationEnv nestedEvalEnv) {
		InternalEvaluator evalVisitor = (InternalEvaluator) getOperationalEnv().getFactory().createEvaluationVisitor(
				parent.getOperationalEnv(), nestedEvalEnv, nestedEvalEnv.createExtentMap(null));
		if (evalVisitor instanceof QvtOperationalEvaluationVisitorImpl) {
			// ensure shared instance of oclAnnotationSupport to avoid repeated OCL parsing
			((QvtOperationalEvaluationVisitorImpl) evalVisitor).oclAnnotationSupport = getOCLAnnotationSupport();
		}
		return evalVisitor;
	}
	
	public Object visitDictLiteralExp(DictLiteralExp dictLiteralExp) {
		Dictionary<Object, Object> result = new DictionaryImpl<Object, Object>();
		for (DictLiteralPart part : dictLiteralExp.getPart()) {
			Object key = visitExpression(part.getKey());
			Object value = visitExpression(part.getValue());
			if(key != getInvalid() && value != getInvalid())
			result.put(key, value);
		}
		
		return result;
	}
	
	@Override
    public Object visitVariableExp(VariableExp<EClassifier, EParameter> v) {
		QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();		
		Variable<EClassifier, EParameter> vd = v.getReferredVariable();
		String varName = vd.getName();		
		Object value = evalEnv.getValueOf(varName);
		
		if(QvtOperationalEnv.THIS.equals(varName)) {
			EClassifier varType = v.getType();
			if(varType instanceof Module) {
				Module referredThisModule = (Module)varType;
				ModuleInstance thisObj = evalEnv.getThisOfType(referredThisModule);
				// only if not null, the variables is part of the QVT type system.
				// otherwise, it may be a custom variable in non-QVT execution context, like ImperativeOCL 
				if(thisObj != null) {
					return thisObj;
				}
			}
		} else if(vd instanceof ModelParameter) {			
			OperationalTransformation transformation = (OperationalTransformation) vd.eContainer();
			TransformationInstance transformationInstance = (TransformationInstance)evalEnv.getThisOfType(transformation);
			assert transformationInstance != null;
			
			ModelInstance model = transformationInstance.getModel((ModelParameter)vd);
			assert model != null;			
			return model;
		}
		
		return value;
	}
	
    /**
	 * Creates evaluation visitor for an non-transformation execution client.
	 * <p>
	 * No main entry operation is available, the execution flow is undefined and
	 * it is the responsibility of the executor client.
	 * </p>
	 * <code>Note:</code>Only helper operation can be executed on the resulting
	 * visitor by an external clients.
	 * 
	 * @see #executeHelperOperation(Helper, Object, List)
	 */
    public static QvtOperationalEvaluationVisitorImpl createNonTransformationExecutionContextVisitor(Context context, ImportToNonTransformCtxHelper importProvider) {    	
		QvtOperationalEnv env = (QvtOperationalEnv)QvtOperationalEnvFactory.INSTANCE.createEnvironment();
		QvtOperationalEvaluationEnv evalEnv = QvtOperationalEnvFactory.INSTANCE.createEvaluationEnvironment(context, null);
    	return createNonTransformationExecutionContextVisitor(env, evalEnv, importProvider);
    }
    
    public static QvtOperationalEvaluationVisitorImpl createNonTransformationExecutionContextVisitor(
    		QvtOperationalEnv env, QvtOperationalEvaluationEnv evalEnv, ImportToNonTransformCtxHelper importsProvider) {
    	
    	QvtOperationalEvaluationVisitorImpl visitor = new QvtOperationalEvaluationVisitorImpl(env, evalEnv);    	
    	InternalEvaluationEnv internalEvalEnv = evalEnv.getAdapter(InternalEvaluationEnv.class);
		
    	ThisInstanceResolver importsByAccess = importsProvider.createImportedInstanceResolver();
		internalEvalEnv.setThisResolver(importsByAccess);
		
		// initialize those module only	newly instantiated, therefore uninitialized yet
		for (ModuleInstance nextModuleToInit : importsProvider.getModuleInstances(false)) {
			// the call bellow makes sure that all of its imported modules gets initialized 
			// if not done already due to other dependent modules
			ModuleInstance.Internal internalModule = nextModuleToInit.getAdapter(ModuleInstance.Internal.class);
			// check if initialized as the module we iterate through might cross-refence, so 
			// get initialized in the meantime
			if(!internalModule.isInitialized()) {			
				visitor.initModule(nextModuleToInit, null);
			}
		}
		
		return visitor;
    }
        
    public static QvtOperationalEvaluationVisitor createVisitor(QvtOperationalEnv env, QvtOperationalEvaluationEnv evalEnv) {
    	return new QvtOperationalEvaluationVisitorImpl(env, evalEnv).createInterruptibleVisitor();
    }
            
	@Override
	public EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> getEvaluationEnvironment() {
		return myEvalEnv;
	}
	
	public void setOperationalEvaluationEnv(QvtOperationalEvaluationEnv evalEnv) {
		myEvalEnv = evalEnv;
    }
	
	protected void pushedStack(QvtOperationalEvaluationEnv env) {
	}	
	
	protected void poppedStack() {
	}
	

    public IContext getContext() {
        return getOperationalEvaluationEnv().getContext();
    }
    
    public void notifyAfterDeferredAssign(final AssignExp assignExp, Object leftValue) {
    	// do nothing special here, subclasses may customize
    }
    
	@Override
    public Object visitIfExp(IfExp<EClassifier> ie) {
		// get condition
		OCLExpression<EClassifier> condition = ie.getCondition();

		// evaluate condition
		Object condVal = visitExpression(condition);		
		if (isUndefined(condVal)) {
			return getInvalid();
		}
		
		Boolean condValBool = (Boolean) condVal;
		if (condValBool.booleanValue()) {
			return visitExpression(ie.getThenExpression());
        }
		if (ie.getElseExpression() != null) {
			return visitExpression(ie.getElseExpression());
		}
		return null;
	}

    @SuppressWarnings("unchecked")
	public Object visitAssignExp(final AssignExp assignExp) {
		QvtOperationalEvaluationEnv env = getOperationalEvaluationEnv();
		InternalEvaluationEnv internEnv = env.getAdapter(InternalEvaluationEnv.class);

		boolean isDeferred = false;
		// TODO: modify the following code for more complex l-values
		OCLExpression<EClassifier> lValue = assignExp.getLeft();
		if (assignExp.getValue().size() == 1) {
			isDeferred = QvtResolveUtil.hasDeferredRightSideValue(assignExp);
			if (isDeferred) {
				Object ownerObj = getAssignExpLValueOwner(lValue);
				if (ownerObj instanceof EObject) {
					PropertyCallExp<EClassifier, EStructuralFeature> lvalueExp = (PropertyCallExp<EClassifier, EStructuralFeature>) assignExp
							.getLeft();
					EStructuralFeature referredProperty = lvalueExp.getReferredProperty();
					internEnv
							.setLastAssignmentLvalueEval(new EObjectEStructuralFeaturePair((EObject) ownerObj, referredProperty));
				}
			}
		}

		Object exprValue = null;
		for (OCLExpression<EClassifier> exp : assignExp.getValue()) {
			exprValue = visitExpression(exp);
		}

		if (isDeferred) {
			// the source of resolve calls has been evaluated above ->
			// assignment of the left value is not executed now
			// but at deferred time in the end of the transformation
			return null;
		}
		
		if (lValue instanceof VariableExp<?, ?>) {
			VariableExp<EClassifier, EParameter> varExp = (VariableExp<EClassifier, EParameter>) lValue;
			Variable<EClassifier, EParameter> referredVariable = varExp.getReferredVariable();
			if (referredVariable != null) {
				String varName = referredVariable.getName();
				Object oldValue = getRuntimeValue(varName);
				EClassifier variableType = lValue.getType();
				
				Object newValue = env.assign(variableType, oldValue, exprValue, assignExp.isIsReset());
				
				replaceInEnv(varName, newValue, variableType);
			}
		} else if (lValue instanceof PropertyCallExp<?, ?>) {
			Object ownerObj = getAssignExpLValueOwner(lValue);
			if (ownerObj instanceof EObject) {
				EObject oldIP = setCurrentEnvInstructionPointer(assignExp);
				env.callSetter((EObject) ownerObj,
						((PropertyCallExp<EClassifier, EStructuralFeature>) lValue).getReferredProperty(), exprValue,
						isUndefined(exprValue), assignExp.isIsReset());
				setCurrentEnvInstructionPointer(oldIP);
			}
		} else {
			throw new UnsupportedOperationException("Unsupported LValue type: " + ((lValue == null) ? null : lValue.getType())); //$NON-NLS-1$
		}

		return exprValue;
    }
    
    private Object getAssignExpLValueOwner(OCLExpression<EClassifier> lValue) {
        if (lValue instanceof PropertyCallExp<?, ?>) {
            @SuppressWarnings("unchecked")
            PropertyCallExp<EClassifier, EParameter> propertyCallExp = (PropertyCallExp<EClassifier, EParameter>) lValue;
            OCLExpression<EClassifier> sourceExp = propertyCallExp.getSource();
            Object owner = visitExpression(sourceExp);
                        
            // obtain correct owner for features of modules, which are possibly defined in an extended module that is not an explicit supertype (fixed by bug 302594/310991)
            if (owner instanceof ModuleInstance) {
            	
            	ModuleInstance moduleInstance = (ModuleInstance) owner;
            	
            	Object property = ((PropertyCallExp<?,?>) lValue).getReferredProperty();
            	
            	EClassifier containingClassifier = getUMLReflection().getOwningClassifier(property);
            	if (containingClassifier instanceof Module) {
            		owner = moduleInstance.getThisInstanceOf((Module) containingClassifier);
            	}	
            	
            }
           
            return owner;
        }
               
        return null;
    }

    private Object visitConfigProperty(EStructuralFeature configProperty) {
		setCurrentEnvInstructionPointer(configProperty);
		
    	IContext context = getOperationalEvaluationEnv().getContext();

        Object rawValue = context.getConfigProperty(configProperty.getName());
        EClassifier propertyType = configProperty.getEType();
        
        Object value = rawValue;
        if (!context.getConfigProperties().containsKey(configProperty.getName())) {
        	//leave non-specified configuration property as undefined
        	//value = EvaluationUtil.createInitialValue(propertyType, getEnvironment().getOCLStandardLibrary(), getEvaluationEnvironment());
        }
        else if(rawValue instanceof String && propertyType != getEnvironment().getOCLStandardLibrary().getString()) {
        	try {
        		value = ConversionUtils.createFromString(propertyType, (String) rawValue);
        	}
        	catch (IllegalArgumentException e) {
        		value = getInvalid();
        	}
        	
        }

        if(value == getInvalid()) {
        	// we failed to parse the value
        	throwQVTException(new QvtRuntimeException(NLS.bind(EvaluationMessages.QvtOperationalEvaluationVisitorImpl_invalidConfigPropertyValue, configProperty.getName(), rawValue)));
        }
        
        return value;
    }

    public Object visitEntryOperation(EntryOperation entryOperation) {    
        visitImperativeOperation(entryOperation);
        return new OperationCallResult(visitOperationBody(entryOperation.getBody()), getOperationalEvaluationEnv());
    }
    
    public Object visitHelper(Helper helper) {
        visitImperativeOperation(helper);
        
        if (helper.isIsBlackbox()) {
        	Object result = doVisitBlackboxOperation(helper);        	
        	return new OperationCallResult(result, getOperationalEvaluationEnv());
        }
        
        return new OperationCallResult(visitOperationBody(helper.getBody()), getOperationalEvaluationEnv());
    }

    public Object visitImperativeOperation(ImperativeOperation imperativeOperation) {

        List<Object> args = getOperationalEvaluationEnv().getOperationArgs();
        Iterator<Object> argIt = args.iterator();

        QvtOperationalEvaluationEnv env = getOperationalEvaluationEnv();
        for (EParameter nextParam : imperativeOperation.getEParameters()) {
            if (!argIt.hasNext()) {
                throw new IllegalArgumentException("arguments mismatch: got" + args + ", expected " + //$NON-NLS-1$ //$NON-NLS-2$
                        imperativeOperation.getEParameters());
            }

            VarParameter param = (VarParameter) nextParam;
            Object arg = argIt.next();

            if (param.getKind() != DirectionKind.OUT) {
            	addToEnv(param.getName(), arg, param.getEType());
            }
        }

        EClassifier contextType = QvtOperationalParserUtil.getContextualType(imperativeOperation);
        if (contextType != null) {
            addToEnv(Environment.SELF_VARIABLE_NAME, env.getOperationSelf(), contextType);
        }

		pushedStack(getOperationalEvaluationEnv());
        return null;
    }
    
    private Object doVisitBlackboxOperation(ImperativeOperation operation) {
    	
    	assert operation.isIsBlackbox() : "Blackbox operation expected"; //$NON-NLS-1$
    	    	
    	QvtOperationalModuleEnv moduleEnv = ASTBindingHelper.resolveModuleEnvironment(operation.eContainer());
    	    	
		Collection<CallHandler> handlers = BlackboxRegistry.INSTANCE.getBlackboxCallHandler(operation, moduleEnv);
    	if (handlers.isEmpty()) {
        	throwQVTException(new QvtRuntimeException(NLS.bind(EvaluationMessages.NoBlackboxOperationFound,
        			QvtOperationalParserUtil.safeGetMappingQualifiedName(getOperationalEnv(), operation))));
    	}
    	if (handlers.size() > 1) {
        	throwQVTException(new QvtRuntimeException(NLS.bind(EvaluationMessages.AmbiguousBlackboxOperationFound,
        			QvtOperationalParserUtil.safeGetMappingQualifiedName(getOperationalEnv(), operation))));
    	}

    	QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
		return handlers.iterator().next().invoke(evalEnv.getThisOfType(QvtOperationalParserUtil.getOwningModule(operation)), evalEnv.getOperationSelf(), evalEnv.getOperationArgs().toArray(), evalEnv);
    }

    public Object visitLibrary(Library library) {
        return null;
    }

    public Object visitLocalProperty(EStructuralFeature property) {
    	OCLExpression<EClassifier> initExp = QvtOperationalParserUtil.getInitExpression(property);
    	if(initExp != null) {
    		return visitExpression(initExp);
    	}
    	
    	return null;
    }
    
	public Object visitContextualProperty(ContextualProperty contextualProperty) {
		if(contextualProperty.getInitExpression() != null) {
			return visitExpression(contextualProperty.getInitExpression());
		}
		return null;
	}
    
    private boolean isWhenPreconditionSatisfied(MappingOperation mappingOperation) {
    	for (OCLExpression<EClassifier> nextCond : mappingOperation.getWhen()) {
    		if(!Boolean.TRUE.equals(visitExpression(nextCond))) {
    			return false;
    		}
		}
    	return true;
    }
    
    private boolean isWherePreconditionSatisfied(MappingOperation mappingOperation) {
    	if (false == mappingOperation.getWhere() instanceof BlockExp) {
    		return true;
    	}
    	for (OCLExpression<EClassifier> nextCond : ((BlockExp) mappingOperation.getWhere()).getBody()) {
    		if(!Boolean.TRUE.equals(visitExpression(nextCond))) {
    			return false;
    		}
		}
    	return true;
    }
    
    private void setupInitialResultValue(MappingBody mappingBody) {
    	ImperativeOperation operation = mappingBody.getOperation();
    	QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
		// Note: the variables for result parameters may not be set or existing yet
		// define variables if not done already by the reusing mapping caller so
    	// avoid overriding values    	
    	for (VarParameter resultParam : operation.getResult()) {    		
    		if(evalEnv.getValueOf(resultParam.getName()) == null) {
    			Object initialValue = EvaluationUtil.createInitialValue(resultParam.getEType(), getStandardLibrary(), evalEnv);
    			replaceInEnv(resultParam.getName(), initialValue, resultParam.getEType());    			
    		}
		}
    	
    	if(operation.getResult().size() > 1) {
    		if(evalEnv.getValueOf(Environment.RESULT_VARIABLE_NAME) == null) {
    			Object initialValue = EvaluationUtil.createInitialValue(operation.getEType(), getStandardLibrary(), evalEnv);
    			replaceInEnv(Environment.RESULT_VARIABLE_NAME, initialValue, operation.getEType());
    		}
    	}    	
    }
    
    public Object visitMappingBody(MappingBody mappingBody) {
		QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
        MappingOperation currentMappingCalled = (MappingOperation) mappingBody.getOperation();
		
		setupInitialResultValue(mappingBody);
    	
        for (OCLExpression<EClassifier> initExp : mappingBody.getInitSection()) {
        	visitExpression(initExp);
        }
                
        if(!mappingBody.getInitSection().isEmpty()) {
        	// setup a meaningful IP after init section to avoid pointing to the last expression of init 
        	// section, so in case of error a proper error location can be computed        	
        	setCurrentEnvInstructionPointer(currentMappingCalled);
        }
        
		Object result = createOrGetResult(currentMappingCalled);
		createOutParams(currentMappingCalled);		
		setOutParamsValues(currentMappingCalled, myEvalEnv.getOperationArgs());
        TraceUtil.addTraceRecord(getOperationalEvaluationEnv(), currentMappingCalled);
		
		// call inherited mappings
		if(!currentMappingCalled.getInherited().isEmpty()) {
			for (MappingOperation extendedMapping : currentMappingCalled.getInherited()) {
				
				// consider overriding mapping
	    		ImperativeOperation overridingOper = EvaluationUtil.getOverridingOperation(getOperationalEvaluationEnv(), extendedMapping);
	    		if (overridingOper instanceof MappingOperation) {
	    			extendedMapping = (MappingOperation) overridingOper;
	    		}
				
				executeImperativeOperation(extendedMapping, evalEnv.getOperationSelf(), evalEnv.getOperationArgs(), true);				
			}
		}

        visitOperationBody(mappingBody);

        // TODO investigate possibility to modify result
        for (OCLExpression<EClassifier> endExp : mappingBody.getEndSection()) {
        	visitExpression(endExp);
        }
        
		// call merged mappings
		callMergedMappings(currentMappingCalled, evalEnv);
		
        return result;
    }
    
    private void callMergedMappings(MappingOperation mappingOperation, QvtOperationalEvaluationEnv evalEnv) {
		for (MappingOperation extendedMapping : mappingOperation.getMerged()) {
			// consider overriding mapping
    		ImperativeOperation overridingOper = EvaluationUtil.getOverridingOperation(getOperationalEvaluationEnv(), extendedMapping);
    		if (overridingOper instanceof MappingOperation) {
    			extendedMapping = (MappingOperation) overridingOper;
    		}
			
			executeImperativeOperation(extendedMapping, evalEnv.getOperationSelf(), evalEnv.getOperationArgs(), true);				
		}
    }

    public Object visitMappingCallExp(MappingCallExp mappingCallExp) {
        return visitOperationCallExp(mappingCallExp);
    }

    @Override
    public Object visitOperationCallExp(OperationCallExp<EClassifier, EOperation> operationCallExp) {
    	// TODO - review the note bellow
    	// set IP of the current stack (represented by the top operation fEnv)
    	// to the this operation call in order to reflect this call position 
    	// in possible QVT stack, in case an exception is thrown 
        EObject oldIP = setCurrentEnvInstructionPointer(operationCallExp);
        Object result = doVisitOperationCallExp(operationCallExp);    	        
        setCurrentEnvInstructionPointer(oldIP);
        return result;
    }    
    
    protected Object doVisitOperationCallExp(OperationCallExp<EClassifier, EOperation> operationCallExp) {
        EOperation referredOperation = operationCallExp.getReferredOperation();
                
        boolean isImperative = QvtOperationalUtil.isImperativeOperation(referredOperation);
		if (isImperative && !CallHandler.Access.hasHandler(referredOperation)) {
			Object source = visitExpression(operationCallExp.getSource());
			if (((ImperativeOperation) referredOperation).getContext() != null) {
				source = EvaluationUtil.doImplicitListCoercion(
						((ImperativeOperation) referredOperation).getContext().getEType(), source);
			}
            List<Object> args = makeArgs(operationCallExp);
            // does not make sense continue at all, call on invalid results in invalid 
        	if(source == getInvalid()) {
        		return source;
        	}

            ImperativeOperation method = null;
            if (QvtOperationalParserUtil.isOverloadableMapping(referredOperation, getOperationalEnv())) {                
        		EOperation actualOperation = findOperationByActualSourceType(source, referredOperation);
				if(actualOperation instanceof ImperativeOperation) { 
					method = (ImperativeOperation) actualOperation;
				}
            }
            
    		if((method == null) && referredOperation instanceof ImperativeOperation) {
    			// we can't dispatch non-imperative as we already evaluated the source 
    			method = (ImperativeOperation)referredOperation;
    		}

            if(method != null) {
            	
            	if (QvtOperationalParserUtil.isContextual(method) && source == null) {
            		if (QvtOperationalParserUtil.getContextualType(method) != getStandardLibrary().getOclVoid()) {
            			return getInvalid();
            		}
            	}
            	
            	if(operationCallExp instanceof ImperativeCallExp) {
            		ImperativeCallExp imperativeCall = (ImperativeCallExp) operationCallExp;
            		if(imperativeCall.isIsVirtual()) {
            			ImperativeOperation overridingOper = EvaluationUtil.getOverridingOperation(getOperationalEvaluationEnv(), method);
            			if(overridingOper != null) {
            				method = overridingOper;
            			}
            		}
            	}

				OperationCallResult opResult = executeImperativeOperation(method, source, args, false);
				if (operationCallExp instanceof MappingCallExp && opResult instanceof MappingCallResult
						&& method instanceof MappingOperation) {
					if (((MappingCallExp) operationCallExp).isIsStrict() && ((MappingCallResult) opResult).isPreconditionFailed()) {
						throwQVTException(new QvtAssertionFailed(NLS.bind(EvaluationMessages.MappingPreconditionFailed,
								method.getName())));
					}
					retrieveOutArgs(operationCallExp, ((MappingCallResult) opResult).myEvalEnv.getOperationArgs(),
							(MappingOperation) method);
				}

				return EvaluationUtil.doImplicitListCoercion(referredOperation.getEType(), opResult.myResult);
            }
        }

        Object result = null;
        try {
        	result = super.visitOperationCallExp(operationCallExp);
        }
        catch (QvtRuntimeException e) {
        	throw e;
		}
        catch (RuntimeException ex) {
            //Logger.getLogger().log(Logger.WARNING, "QvtEvaluator: failed to evaluate oclOperationCall", ex);//$NON-NLS-1$
        	result = getInvalid();
        }
        
        return result;
    }

    /**
	 * Finds operation based on the actual type of the source object as per
	 * virtual call semantics.
	 * 
	 * @param source
	 *            the self instance of the contextual type
	 * @param referredOperation
	 *            the operation referred by the call expresion in the AST
	 * @return the actual operation to call, which is either the passed referred
	 *         operation or another one defined in the bottom-most class in the
	 *         type hierarchy of the source object
	 */
	private EOperation findOperationByActualSourceType(Object source, EOperation referredOperation) {
		EOperation actualOperation = referredOperation;
		IVirtualOperationTable vTable = getVirtualTable(referredOperation);
		if(vTable != null) {
			EClassifier sourceEClass = getEvaluationEnvironment().getType(source);
			if(sourceEClass != null) {
				InternalEvaluationEnv internEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
				EOperation oper = vTable.lookupActualOperation(sourceEClass, getEnvironment(), internEnv);
				if(oper != null) {
					actualOperation = oper;
				}
			}
		}
		return actualOperation;
	}
	
    @Override
    public Object visitEnumLiteralExp(EnumLiteralExp<EClassifier, EEnumLiteral> el) {
        return el.getReferredEnumLiteral().getInstance();
    }

    /**
	 * @return result object or <code>null</code> in case that no result
	 *         variable is declared and <code>OclInvalid</code> in case the
	 *         precondition failed and the body was not executed.
	 */
    public Object visitMappingOperation(MappingOperation mappingOperation) {
        visitImperativeOperation(mappingOperation);

        QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
		if (!isWhenPreconditionSatisfied(mappingOperation)) {
        	// return Invalid, to indicate precondition failure to the caller. It is used instead of
        	// of 'null' as it is a legal value for no result inout mapping, even
        	// the precondition holds
 
        	return new MappingCallResult(null, evalEnv, MappingCallResult.PRECOND_FAILED);
        }
		
		MappingCallResult result = executeMappingBody(mappingOperation, evalEnv);
		if (!isWherePreconditionSatisfied(mappingOperation)) {
			throwQVTException(new QvtAssertionFailed(NLS.bind(EvaluationMessages.MappingPostconditionFailed,
					mappingOperation.getName())));
		}
		return result;
    }

	protected MappingCallResult executeMappingBody(MappingOperation mappingOperation, QvtOperationalEvaluationEnv evalEnv) {
        // check the traces whether the relation already holds
		TraceRecord traceRecord = TraceUtil.getTraceRecord(evalEnv, mappingOperation);
		if (traceRecord != null) {
			return new MappingCallResult(TraceUtil.fetchResultFromTrace(evalEnv, traceRecord), evalEnv, MappingCallResult.FETCHED_FROM_TRACE);
		}
		
		if(!mappingOperation.getDisjunct().isEmpty()) {
			return dispatchDisjunctMapping(mappingOperation);
		}
		
		if (mappingOperation.isIsBlackbox()) {        	
			Object result = doVisitBlackboxOperation(mappingOperation);        	
			if (isUndefined(result)) {
				throwQVTException(new QvtRuntimeException(NLS.bind(EvaluationMessages.BlackboxMappingFailedToAssignResult,
						QvtOperationalParserUtil.safeGetMappingQualifiedName(getOperationalEnv(), mappingOperation))));
			}
			
			replaceInEnv(Environment.RESULT_VARIABLE_NAME, result, mappingOperation.getEType());
		    TraceUtil.addTraceRecord(getOperationalEvaluationEnv(), mappingOperation);
		    
		    // call merged mappings
			callMergedMappings(mappingOperation, evalEnv);
		    
		    return new MappingCallResult(result, evalEnv, MappingCallResult.BODY_EXECUTED);        	
		}
		                                		
		return new MappingCallResult(((OperationBodyImpl) mappingOperation.getBody()).accept(getVisitor()), evalEnv,
				MappingCallResult.BODY_EXECUTED);
	}

    public Object execute(OperationalTransformation transformation) throws QvtRuntimeException {
    	boolean isSuppressLoggin = myIsSuppressLoggin;
    	try {
    		myIsSuppressLoggin = true;
    		return transformation.accept(getVisitor());
    	} finally {
    		myIsSuppressLoggin = isSuppressLoggin;
		}    		
    }
    
    public Object visitModule(Module module) {
        if (module instanceof OperationalTransformation == false) {
            throw new IllegalArgumentException(NLS.bind(EvaluationMessages.ExtendedOclEvaluatorVisitorImpl_ModuleNotExecutable, module.getName()));
        }
    	        
		try {
			return doVisitTransformation((OperationalTransformation) module);
		} 
		catch (QvtRuntimeException e) {
			if (!myIsSuppressLoggin) {
				StringWriter strWriter = new StringWriter();
				PrintWriter printWriter = new PrintWriter(strWriter);
				e.printQvtStackTrace(printWriter);
	
				Log logger = getContext().getLog();
				logger.log(EvaluationMessages.TerminatingExecution);
				logger.log(strWriter.getBuffer().toString());
			}			
			throw e;
		} finally {
			IntermediatePropertyModelAdapter.cleanup(module);
			getOperationalEvaluationEnv().cleanup();
		}
    }        
        
    /**
	 * Executes the given helper operation with actual arguments passed.
	 * 
	 * @param method
	 *            the helper operation to execute
	 * @param self
	 *            the contextual instance in case of contextual operation,
	 *            otherwise the default instance of the module which defines the
	 *            called operation
	 * @param args
	 *            the actual parameter values
	 * @return return the value directly returned by the operation
	 */
	public Object executeHelperOperation(Helper method, Object self, List<Object> args) {
		Helper actualHelper = method;
		EOperation actualOperation = findOperationByActualSourceType(self, method);
		if(actualOperation instanceof Helper) { 
			actualHelper = (Helper) actualOperation;			
		} else {
			// Remark - the case when the actual operation is not imperative but 
			// a meta-model operation the virtual call will be dispatched by using 			
			// a normal operation call
			return getEvaluationEnvironment().callOperation(method, -1, self, args.toArray(new Object[args.size()]));
		}
		
		OperationCallResult result = executeImperativeOperation(actualHelper, self, args, false);
		return result.myResult;
	}
    
	@SuppressWarnings("unchecked")
	public Object visitInstantiationExp(InstantiationExp objectExp) { 
		// should instantiate the module transformation
		EClass _class = objectExp.getInstantiatedClass();
		if (_class instanceof OperationalTransformation) {
				
			EList<org.eclipse.ocl.ecore.OCLExpression> formalArguments = objectExp.getArgument();		
			List<ModelInstance> actualArguments = new ArrayList<ModelInstance>(formalArguments.size());
	
			for (OCLExpression<EClassifier> nextArg : formalArguments) {
				Object argVal = visitExpression(nextArg);	
				if(argVal instanceof ModelInstance == false) {
					throwQVTException(new QvtRuntimeException(EvaluationMessages.QvtOperationalEvaluationVisitorImpl_UndefModelParamInTransf));
				}
				ModelInstance modelInstance = (ModelInstance) argVal;
				actualArguments.add(modelInstance); 
			}
	
			OperationalTransformation targetTransf = (OperationalTransformation)_class;
			QvtOperationalEvaluationEnv currentEnv = getOperationalEvaluationEnv();		
			// create a nested environment for constructor invocation representing 
			// the root environment of explicitly called transformation		
			// Empty default context, no configuration property is available
			// Remark: Can we set configuration property in the concrete syntax on the explicit transf object.
			// bug 416584: Now we need to access configuration properties of non-entry modules
			Context nestedContext = EvaluationUtil.createAggregatedContext(currentEnv);
			
			QvtOperationalEnvFactory envFactory = getOperationalEnv().getFactory();
			QvtOperationalEvaluationEnv nestedEvalEnv = envFactory.createEvaluationEnvironment(nestedContext, null);
			
			//bug 392153: reuse existing trace for nested environment
			Trace trace = currentEnv.getAdapter(InternalEvaluationEnv.class).getTraces();
			nestedEvalEnv.getAdapter(InternalEvaluationEnv.class).setTraces(trace);
			
			// send arguments into the entry operation
			nestedEvalEnv.getOperationArgs().addAll(actualArguments);
			// Use per transformation instance visitor 
			InternalEvaluator nestedVisitor = createNestedEvaluationVisitor(this, nestedEvalEnv);
			try {
				setOperationalEvaluationEnv(nestedEvalEnv);
				
				ModuleInstance moduleInstance = nestedVisitor.callTransformationImplicitConstructor(targetTransf, actualArguments);
				
				return moduleInstance;
			} finally {
				setOperationalEvaluationEnv(currentEnv);
			}
		}
		else {
	        Object owner = createInstance(objectExp.getType(), (ModelParameter) objectExp.getExtent());

			EList<org.eclipse.ocl.ecore.OCLExpression> formalArguments = objectExp.getArgument();		
			List<Object> actualArguments = new ArrayList<Object>(formalArguments.size());
	
			for (OCLExpression<EClassifier> nextArg : formalArguments) {
				Object argVal = visitExpression(nextArg);	
				actualArguments.add(argVal); 
			}

			Adapter adapter = EcoreUtil.getAdapter(objectExp.eAdapters(), ConstructorOperationAdapter.class);
			if (adapter != null) {
				Constructor constructorOp = ((ConstructorOperationAdapter) adapter).getReferredConstructor();
				
				for (int i = 0, in = constructorOp.getEParameters().size(); i < in; ++i) {
					actualArguments.set(i, EvaluationUtil.doImplicitListCoercion(
							constructorOp.getEParameters().get(i).getEType(), actualArguments.get(i)));
				}

				executeImperativeOperation(constructorOp, owner, actualArguments, false);
			}
			else {
				if (objectExp.getArgument().isEmpty()) {
					// it's OK since default constructor is called
				}
				else if (objectExp.getEType() instanceof CollectionType<?,?> && owner instanceof Collection<?>) {
					((Collection<Object>) owner).addAll(actualArguments);
				}
				else {
					throwQVTException(new QvtRuntimeException("Undefined constructor is called")); //$NON-NLS-1$
				}
			}
			
	        return owner;
		}
	}
	
	public TransformationInstance callTransformationImplicitConstructor(OperationalTransformation transformation, List<ModelInstance> transfArgs) {
    	ModuleInstanceFactory eFactory = (ModuleInstanceFactory)transformation.getEFactoryInstance();
		assert eFactory != null : "Module class must have factory"; //$NON-NLS-1$
		
		TransformationInstance instance = (TransformationInstance) eFactory.create(transformation);
		// Note: need to make the main executed transf available via this
		// so all super module have access to env::getCurrentTransformation()
		getEvaluationEnvironment().add(QvtOperationalEnv.THIS, instance);
		
		ModelParameterHelper modelParameters = new ModelParameterHelper(transformation, transfArgs);
		initModule(instance, modelParameters);
		
		CallHandler handler = createTransformationHandler();
		InternalTransformation internTransf = instance.getAdapter(InternalTransformation.class);		
		internTransf.setTransformationHandler(handler);
		
		// we are initialized set back the pointer to the module 
		setCurrentEnvInstructionPointer(transformation);		
		return instance;
	}
	
	private CallHandler createTransformationHandler() {
		return new CallHandler() {
			public OperationCallResult invoke(ModuleInstance moduleInstance, Object source, Object[] args, QvtOperationalEvaluationEnv evalEnv) {
				assert (args.length == 0) : "transformation instance must be invoked with zero arguments";
				
				TransformationInstance transformationInstance = (TransformationInstance) source;
				
				try {
					evaluateModelParameterConditions(transformationInstance, evalEnv);
					
					OperationalTransformation transformation = transformationInstance.getTransformation();
					
					if (transformation.isIsBlackbox()) {
						QvtOperationalModuleEnv moduleEnv = ASTBindingHelper.resolveModuleEnvironment(transformationInstance.getModule());
						
						Collection<CallHandler> handlers = BlackboxRegistry.INSTANCE.getBlackboxCallHandler(
								transformation, moduleEnv);
						if (handlers.isEmpty()) { 
							throwQVTException(new QvtRuntimeException(NLS.bind(EvaluationMessages.NoBlackboxOperationFound,
									QvtOperationalParserUtil.safeGetQualifiedName(getOperationalEnv(), transformation))));
						}
						if (handlers.size() > 1) {
							throwQVTException(new QvtRuntimeException(NLS.bind(EvaluationMessages.AmbiguousBlackboxOperationFound,
									QvtOperationalParserUtil.safeGetQualifiedName(getOperationalEnv(), transformation))));
						}
									    	
						List<Object> actualArgs = makeBlackboxTransformationArgs(transformationInstance, evalEnv);		    	
						Object result = handlers.iterator().next().invoke(transformationInstance, source, actualArgs.toArray(), evalEnv);					
						
						return new OperationCallResult(result, evalEnv);
					}
					else {
						return runMainEntry(transformation, makeEntryOperationArgs(transformation));
					}
				} finally {
					transformationInstance.getAdapter(InternalTransformation.class).dispose();
				}	
			}
		};
	}
		
	// FIXME - review the strange case of having various return types
	private Object doVisitTransformation(OperationalTransformation transformation) {
        
        QvtOperationalEvaluationEnv evaluationEnv = getOperationalEvaluationEnv();        
		List<ModelInstance> modelArgs = EvaluationUtil.getTransfromationModelArguments(evaluationEnv, transformation);		

		TransformationInstance moduleInstance = callTransformationImplicitConstructor(transformation, modelArgs); 
				
		InternalTransformation internTransf = moduleInstance.getAdapter(InternalTransformation.class);		
		
		CallHandler handler = internTransf.getTransformationHandler();
        			
        // call main entry operation or blackbox implementation
        OperationCallResult callResult = (OperationCallResult) handler.invoke(
        		null, 
        		moduleInstance,
        		Collections.emptyList().toArray(), 
        		evaluationEnv);
        
        QvtEvaluationResult evalResult = EvaluationUtil.createEvaluationResult(callResult.myEvalEnv);
        
        if (evalResult.getModelExtents().isEmpty()) {
            if (callResult.myResult instanceof EObject) {
                // compatibility reason, make the main() operation return value available in an extent
            	ModelParameterExtent modelParameter = new ModelParameterExtent(
            			Collections.singletonList((EObject) callResult.myResult), null, null);
            	evaluationEnv.addModelExtent(modelParameter);
                evalResult.getModelExtents().add(modelParameter.getContents());
            } else {
                return callResult.myResult;
            }
        }
        
        return evalResult;
    }
				
	protected void processDeferredTasks() {
		InternalEvaluationEnv internalEvalEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
		internalEvalEnv.processDeferredTasks();
	}

	public Object visitModuleImport(ModuleImport moduleImport) {
        return null;
    }

    public Object visitObjectExp(ObjectExp objectExp) {
        InternalEvaluationEnv internEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
        internEnv.setCurrentIP(objectExp);
    	
        Object owner = getOutOwner(objectExp);

    	if(objectExp.getBody() != null) {
    		EList<org.eclipse.ocl.ecore.OCLExpression> contents = objectExp.getBody().getContent();        
	        for (OCLExpression<EClassifier> exp : contents) {
	        	visitExpression(exp);    	
	        }
    	}
    	
    	// owner may have changed in body content, so retrieve it again (fixed by bug 388325)
    	owner = getOutOwner(objectExp);
    	
        if (getOperationalEnv().isTemporaryElement(objectExp.getName())) {
            getOperationalEvaluationEnv().remove(objectExp.getName());
        }

        return owner;
    }

    public Object visitReturnExp(ReturnExp returnExp) {
    	Object value = null;
    	OCLExpression<EClassifier> valueExp = returnExp.getValue();
    	if(valueExp != null) {
    		value = visitExpression(valueExp);
    	}
    	// Wrap the result of the expression in an OperationCallResult object.
    	// This type breaks control flow, so the value arrives directly at its
    	// calling operation, where it is unwrapped again and returned.
		return new OperationCallResult(value, getOperationalEvaluationEnv());
    }
    
    public Object visitOperationBody(OperationBody operationBody) {
        Object result = null;
        for (OCLExpression<EClassifier> exp : operationBody.getContent()) {
        	result = visitExpression(exp);
        	
        	// If control flow was broken (by means of a return statement,
        	// stop executing the next lines and return this result.
        	if(result instanceof BreakingResult) {
	        	if(result instanceof OperationCallResult) {
	        		result = ((OperationCallResult)result).myResult;
	        	}
	        	else {
	        		result = null;
	        	}
	        	break;
        	}
        }
        
        ImperativeOperation operation = operationBody.getOperation();
        
        if(operation.getEType() == getStandardLibrary().getOclVoid()) {
        	result = null;
        }
        
        if(operation.getResult().size() > 1) {
        	return createTupleResult(operation);
        }
        return result;
    }

    public Object visitVarParameter(VarParameter varParameter) {
        return null;
    }

    public Object visitVariableInitExp(VariableInitExp variableInitExp) {
        org.eclipse.ocl.ecore.Variable referredVariable = variableInitExp.getReferredVariable();
        OCLExpression<EClassifier> initExpression = referredVariable.getInitExpression();
        Object value = null;
		if(initExpression != null) {
			value = visitExpression(initExpression);
			// check that collection is initialized to empty collection in case of 'null' 
		} else { 
			value = EvaluationUtil.createInitialValue(referredVariable.getType(), getEnvironment().getOCLStandardLibrary(),
					getEvaluationEnvironment());
		}
		
        replaceInEnv(referredVariable.getName(), 
        		EvaluationUtil.doImplicitListCoercion(variableInitExp.getType(), value), variableInitExp.getType());
        
        return variableInitExp.isWithResult() ? value : null;
    }

    public Object visitBlockExp(BlockExp blockExp) {
        return visitBlockExpImpl(blockExp.getBody(), blockExp.eContainer() instanceof ImperativeOperation);
    }

    private Object visitBlockExpImpl(EList<org.eclipse.ocl.ecore.OCLExpression> expList, boolean isInImperativeOper) {
    	List<String> scopeVars = null;
    	
    	Object result = null;
    	
        for (OCLExpression<EClassifier> exp : expList) {
        	if((exp instanceof VariableInitExp) && !isInImperativeOper) {
        		if(scopeVars == null) {
        			scopeVars = new LinkedList<String>();
        		}
        		VariableInitExp varInitExp = (VariableInitExp) exp;
        		scopeVars.add(varInitExp.getName());
        	}
        	
        	result = visitExpression(exp);
        	if(result instanceof BreakingResult) {
        		break;
        	}
        	// Return null, unless control flow is broken (by break, continue or return).
        	// When control flow is broken, propagate this upward in the AST.
        	result = null;
        }
        
        if(scopeVars != null) {
			EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> evalEnv = getEvaluationEnvironment();        	
        	for (String varName : scopeVars) {        		
				evalEnv.remove(varName);
			}
        }
        
        return result;
    }
    
    public Object visitComputeExp(ComputeExp computeExp) {
        Variable<EClassifier, EParameter> returnedElement = computeExp.getReturnedElement();
        Object initExpressionValue = null;
        OCLExpression<EClassifier> initExpression = returnedElement.getInitExpression();
        if (initExpression != null) {
        	initExpressionValue = visitExpression(initExpression);
        }
        replaceInEnv(returnedElement.getName(), initExpressionValue, returnedElement.getType());
        
        Object result = visitExpression(computeExp.getBody());
        
        Object returnedValue = getEvaluationEnvironment().remove(returnedElement.getName()); 
        
        if(result instanceof BreakingResult) {
        	// Control flow was broken (break or continue).
        	// Instead of returning the value, propagate this.
        	return result;
        }

        return returnedValue;
    }

    public Object visitWhileExp(WhileExp whileExp) {
    	Object result = null;
        while (true) {
        	Object condition = visitExpression(whileExp.getCondition());
        	if (Boolean.TRUE.equals(condition)) {
            	result = visitExpression(whileExp.getBody());

            	if(result instanceof BreakingResult) {
            		// Control flow is being broken (break, continue, or return).
            		
            		if(result instanceof BreakResult) {
            			// Result must be null, unless it comes from a return statement.
                		result = null;
                		break;
                	}
                	if(result instanceof ContinueResult) {
            			// Instead of breaking out of the loop, continue with the next iteration.
                		result = null;
                    	continue;
                	}
            		break;
            	}
            } else {
                break;
            }
        }
        
        return result;
    }
    
    private static class SwitchAltExpResult {
    	public Object myCondition;
    	public Object myResult;
    }
    
    public Object visitAltExp(AltExp switchAltExp) {
		SwitchAltExpResult result = new SwitchAltExpResult();
		result.myCondition = visitExpression(switchAltExp.getCondition());
		if (Boolean.TRUE.equals(result.myCondition)) {
			result.myResult = visitExpression(switchAltExp.getBody());
		}
		return result;
    }

    public Object visitSwitchExp(SwitchExp switchExp) {
        for (AltExp altExp : switchExp.getAlternativePart()) {
        	Object altResult = visitExpression(altExp);	
        	if (altResult instanceof SwitchAltExpResult) {
        		if (isUndefined(((SwitchAltExpResult) altResult).myCondition)) {
        			return getInvalid();
        		}
            	if (Boolean.TRUE.equals(((SwitchAltExpResult) altResult).myCondition)) {
                    return ((SwitchAltExpResult) altResult).myResult;
                }
        	}
        	else if (Boolean.TRUE.equals(altResult)) {
                return null;
            }
        }
        OCLExpression<EClassifier> elsePart = switchExp.getElsePart();
        if (elsePart != null) {
        	return visitExpression(elsePart);
        }
        return null;
    }

    /* resolve expressions family */

    public Object visitResolveExp(ResolveExp resolveExp) {
    	if (resolveExp.isIsDeferred()) {
    		InternalEvaluationEnv internalEvalEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
    		if(!internalEvalEnv.isDeferredExecution()) {	        	
	            LateResolveTask lateResolveTask = new LateResolveTask(resolveExp, internalEvalEnv.getLastAssignmentLvalueEval(),
	            		(QvtOperationalEvaluationVisitor) getVisitor(), getOperationalEvaluationEnv(), this);
	            internalEvalEnv.addDeferredTask(lateResolveTask);
	            return null;
    		}
        }
        return QvtResolveUtil.resolveNow(resolveExp, this, getOperationalEvaluationEnv());
    }
    
    public Object visitResolveInExp(ResolveInExp resolveInExp) {
        if (resolveInExp.isIsDeferred()) {
        	InternalEvaluationEnv internalEvalEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);        	
        	if(!internalEvalEnv.isDeferredExecution()) {
	            LateResolveInTask lateResolveInTask = new LateResolveInTask(resolveInExp, internalEvalEnv.getLastAssignmentLvalueEval(),
	            		(QvtOperationalEvaluationVisitor) getVisitor(), getOperationalEvaluationEnv(), this);
	            internalEvalEnv.addDeferredTask(lateResolveInTask);            
	            return null;
        	}
        }        
        return QvtResolveUtil.resolveInNow(resolveInExp, this, getOperationalEvaluationEnv());
    }
    
	public Object visitModelType(ModelType modelType) {
		return null;
	}
    
	public Object visitLogExp(LogExp logExp) {
		doVisitLogExp(logExp, getContext().getLog(), null);
		return null;
	}
	
	private String doVisitLogExp(LogExp logExp, Log logger, String messagePrefix) {
		if(logExp.getCondition() != null && !Boolean.TRUE.equals(visitExpression(logExp.getCondition()))) {
			return null;
		}
		Object invalid = getInvalid();
		String invalidRepr = "<Invalid>"; //$NON-NLS-1$
		// process logging level
		Integer level = null;
		EList<OCLExpression<EClassifier>> args = logExp.getArgument();
		if(args.size() > 2) {
			Object levelObj = visitExpression(args.get(2));
			level = NumberConversions.strictConvertNumber(levelObj, Integer.class);
		}

		Object message = visitExpression(args.get(0));
		if(message == null) {
			message = "<null>"; //$NON-NLS-1$
		} else if(message == invalid) {
			message = invalidRepr;
		}
		
		Object logEntry = message;
		if(messagePrefix != null) {
			logEntry = messagePrefix + " : " + message; //$NON-NLS-1$
		}

		Object element = null;
		Object formatedElement = null;
		if(args.size() > 1) {
			element = visitExpression(args.get(1));
			if(element == invalid) {
				formatedElement = invalidRepr;
			} else {
				formatedElement = EvaluationUtil.formatLoggedElement(element);
			}
		}

		if(level == null) {
			if(element == null) {
				logger.log(String.valueOf(logEntry));
			} else {		
				logger.log(String.valueOf(logEntry), formatedElement);
			}
		} else {
			if(element == null) {
				logger.log(level, String.valueOf(logEntry));
			} else {		
				logger.log(level, String.valueOf(logEntry), formatedElement);
			}			
		}
		
		return message.toString();
	}
	
	public Object visitAssertExp(AssertExp assertExp) {		
		Object assertionValue = visitExpression(assertExp.getAssertion());
		
		if(!Boolean.TRUE.equals(assertionValue)) {	
			InternalEvaluationEnv internEvalEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
			Module currentModule = internEvalEnv.getCurrentModule().getModule();
			IModuleSourceInfo moduleSource = ASTBindingHelper.getModuleSourceBinding(currentModule);
			
			String source;
			if(moduleSource != null) {
				source = moduleSource.getSourceURI().lastSegment();
			} else {
				source = EvaluationMessages.UknownSourceLabel;				
			}

			StringBuilder locationBuf = new StringBuilder(source);
			if(assertExp.getStartPosition() >= 0 && moduleSource != null) {
				int lineNum = moduleSource.getLineNumberProvider().getLineNumber(assertExp.getStartPosition());
				locationBuf.append(':').append(lineNum);
			}
							
			String message = NLS.bind(EvaluationMessages.AssertFailedMessage, assertExp.getSeverity(), locationBuf.toString());				
			Log logger = getContext().getLog();
			
			String logMessage = null;
			if(assertExp.getLog() != null) {
				logMessage = doVisitLogExp(assertExp.getLog(), logger, message);
			} else {
				logger.log(message);				
			}
			
			if(SeverityKind.FATAL.equals(assertExp.getSeverity())) {
				String msg = (logMessage == null ? EvaluationMessages.FatalAssertionFailed : logMessage);
				throwQVTException(new QvtAssertionFailed(msg));
			}		
				
		}			
		
		return null;
	}
	
    public Object visitImperativeLoopExp(ImperativeLoopExp imperativeLoopExp) {
        throw new UnsupportedOperationException();
    }
    
    public Object visitForExp(ForExp forExp) {
    	Object sourceValue = visitExpression(forExp.getSource());
        
        if (!isUndefined(sourceValue)) {
            // generate a name for the result variable and add it to the environment
            String resultName = generateName();
            getEvaluationEnvironment().add(resultName, null);
            
            Collection<?> sourceCollection = (Collection<?>) sourceValue;
            // get the list of ocl iterators
            List<Variable<EClassifier, EParameter>> iterators = forExp.getIterator();
            // get the condition expression
            OCLExpression<EClassifier> condition = forExp.getCondition();
            // get the body expression
            OCLExpression<EClassifier> body = forExp.getBody();
            
            // evaluate
            QvtIterationTemplateForExp.getInstance(getVisitor()).evaluate(
                    sourceCollection, iterators, null, condition, body, resultName, "forOne".equals(forExp.getName())); //$NON-NLS-1$

            // remove result name from environment
            getEvaluationEnvironment().remove(resultName);
            
        }
        
        return null;
    }

    public Object visitImperativeIterateExp(ImperativeIterateExp imperativeIterateExp) {
        EClassifier sourceType = imperativeIterateExp.getSource().getType();
        
        if (sourceType instanceof PredefinedType<?>) {
        	Object sourceValue = visitExpression(imperativeIterateExp.getSource());
            
            // value of iteration expression is undefined if the source is
            //   null or OclInvalid
            if (isUndefined(sourceValue)) {
                return getInvalid();
            }
            
            // get initial result value based on the source type
            @SuppressWarnings("unchecked")
            CollectionType<EClassifier, EOperation> collType = (CollectionType<EClassifier, EOperation>) imperativeIterateExp.getSource().getType();
            
            
            Object initResultVal = null;
            if (imperativeIterateExp.getName().equals("xselect")) { //$NON-NLS-1$
                initResultVal = EvaluationUtil.createNewCollectionOfSameKind((Collection<?>) sourceValue);
            } else if (imperativeIterateExp.getName().equals("xcollect")  //$NON-NLS-1$
                    || imperativeIterateExp.getName().equals("collectselect")) { //$NON-NLS-1$
                initResultVal = ((collType instanceof SetType<?,?>) || (collType instanceof BagType<?,?>)) ?
                        CollectionUtil.createNewBag() : CollectionUtil.createNewSequence();
            }

            // generate a name for the result variable and add it to the environment
            String resultName = generateName();
            getEvaluationEnvironment().add(resultName, initResultVal);

            Collection<?> sourceCollection = (Collection<?>) sourceValue;
            // get the list of ocl iterators
            List<Variable<EClassifier, EParameter>> iterators = imperativeIterateExp.getIterator();
            // get the target expression
            Variable<EClassifier, EParameter> target = imperativeIterateExp.getTarget();
            // get the condition expression
            OCLExpression<EClassifier> condition = imperativeIterateExp.getCondition();
            // get the body expression
            OCLExpression<EClassifier> body = imperativeIterateExp.getBody();

            // evaluate
            Object result = null;
            if ("xcollect".equals(imperativeIterateExp.getName())) { //$NON-NLS-1$
                result = QvtIterationTemplateXCollect.getInstance(getVisitor()).evaluate(
                        sourceCollection, iterators, target, condition, body, resultName, false);
            } else if ("xselect".equals(imperativeIterateExp.getName())) { //$NON-NLS-1$
                result = QvtIterationTemplateXSelect.getInstance(getVisitor()).evaluate(
                        sourceCollection, iterators, target, condition, body, resultName, false);
            } else if ("collectselect".equals(imperativeIterateExp.getName())) { //$NON-NLS-1$
                result = QvtIterationTemplateCollectSelect.getInstance(getVisitor()).evaluate(
                        sourceCollection, iterators, target, condition, body, resultName, false);
            } else if ("collectOne".equals(imperativeIterateExp.getName())) { //$NON-NLS-1$
                result = QvtIterationTemplateXCollect.getInstance(getVisitor()).evaluate(
                        sourceCollection, iterators, target, condition, body, resultName, true);
            } else if ("selectOne".equals(imperativeIterateExp.getName())) { //$NON-NLS-1$
                result = QvtIterationTemplateXSelect.getInstance(getVisitor()).evaluate(
                        sourceCollection, iterators, target, condition, body, resultName, true);
            } else if ("collectselectOne".equals(imperativeIterateExp.getName())) { //$NON-NLS-1$
                result = QvtIterationTemplateCollectSelect.getInstance(getVisitor()).evaluate(
                        sourceCollection, iterators, target, condition, body, resultName, true);
            }

            // remove result name from environment
            getEvaluationEnvironment().remove(resultName);

            return result;
        }
        
        String message = NLS.bind(EvaluationMessages.IteratorNotImpl, imperativeIterateExp.getName());
        throw new UnsupportedOperationException(message);
    }
    
	public Object visitConstructor(Constructor constructor) {
        visitImperativeOperation(constructor);
        
        QvtOperationalEvaluationEnv env = getOperationalEvaluationEnv();
        
        if (constructor.isIsBlackbox()) {
        	Object result = doVisitBlackboxOperation(constructor);        	        	
        	return new OperationCallResult(result, env);
        }
        
        env.add(Environment.RESULT_VARIABLE_NAME, env.remove(Environment.SELF_VARIABLE_NAME));
        return new OperationCallResult(visitOperationBody(constructor.getBody()), env);
	}

	public Object visitConstructorBody(ConstructorBody constructorBody) {
		return visitOperationBody(constructorBody);
	}

	public Object visitBreakExp(BreakExp astNode) {
		return BREAK;
	}

	public Object visitCatchtExp(CatchExp astNode) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object visitContinueExp(ContinueExp astNode) {
		return CONTINUE;
	}

	public Object visitDictLiteralPart(DictLiteralPart astNode) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object visitOrderedTupleLiteralExp(OrderedTupleLiteralExp astNode) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object visitOrderedTupleLiteralPart(OrderedTupleLiteralPart astNode) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object visitRaiseExp(RaiseExp raiseExp) {
    	Object value = null;
    	if(raiseExp.getArgument() != null) {
    		value = visitExpression(raiseExp.getArgument());
    	}
    	String argument = (value instanceof String) ? (String)value : null;
		QvtException exception = new QvtException(argument, (EClass)raiseExp.getException());
		exception.setStackQvtTrace(new QvtStackTraceBuilder(getOperationalEvaluationEnv()).buildStackTrace());
		throw exception;
	}

	public Object visitTryExp(TryExp tryExp) {
		try {
            return visitBlockExpImpl(tryExp.getTryBody(), tryExp.eContainer() instanceof ImperativeOperation);
		}
		catch (QvtException exception) {
			boolean processed = false;
			
			OUTERMOST: for (CatchExp catchExp : tryExp.getExceptClause()) {
				for (EClassifier excType : catchExp.getException()) {
					if (EmfUtil.isAssignableFrom(excType, exception.getExceptionType())) { 
						processed = processCatch(catchExp, exception);
						break OUTERMOST;
					}
				}
				if (catchExp.getException().isEmpty()) { // catch all
					processed = processCatch(catchExp, exception);
					break OUTERMOST;
				}
			}
			
			if (!processed) {
				throw exception;
			}
		}
		
		return null;
	}
	
	private boolean processCatch(CatchExp catchExp, QvtException exception) {
		QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
		String varName = null;

		org.eclipse.ocl.ecore.Variable catchVariable = ASTBindingHelper.getCatchVariable(catchExp);
		if (catchVariable != null) {
			ExceptionInstance excObject = null;
			if (exception.getExceptionType().getEPackage() == QvtOperationalStdLibrary.INSTANCE.getStdLibModule()) {
				excObject = QvtOperationalStdLibrary.INSTANCE.getStdlibFactory().createException(exception.getExceptionType(),
						exception.getMessage(), exception.getQvtStackTrace());
			}
			else {
				ExceptionClassInstance exceptionImpl = (ExceptionClassInstance) createInstance(exception.getExceptionType(), null);
				exceptionImpl.setArgument(exception.getMessage());
				exceptionImpl.setStackElements(exception.getQvtStackTrace());
				excObject = exceptionImpl;
			}

			varName = catchVariable.getName();
			evalEnv.add(varName, excObject);
		}
		
		visitBlockExpImpl(catchExp.getBody(), catchExp.eContainer() instanceof ImperativeOperation);
		
		if (varName != null) {
			evalEnv.remove(varName);
		}
		return true;
	}

	public Object visitUnlinkExp(UnlinkExp astNode) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object visitUnpackExp(UnpackExp astNode) {
		// TODO Auto-generated method stub
		return null;
	}
    
    private static synchronized String generateName() {
        return "__qvtresult__" + tempCounter++;//$NON-NLS-1$
    }

	/**
	 * Initializes the model parameters and properties of the given module
	 * instance and all instances associated via import.
	 * 
	 * @param moduleInstance
	 *            the instance to initialize
	 * @param modelParameters
	 *            helper for binding transformation parameters
	 */
    private void initModule(ModuleInstance moduleInstance, ModelParameterHelper modelParameters) {
    	Module type = moduleInstance.getModule();
		QvtOperationalEnv env = (QvtOperationalEnv) getEnvironment();
		QvtOperationalEvaluationEnv currentEvalEnv = getOperationalEvaluationEnv();	

		QvtOperationalEvaluationEnv nestedEvalEnv = (QvtOperationalEvaluationEnv) env.getFactory().createEvaluationEnvironment(getOperationalEvaluationEnv());
		// ensure 'this' instance available in the initialization code
		nestedEvalEnv.add(QvtOperationalEnv.THIS, moduleInstance);
		// propagate arguments, provided it is a transformation module
		nestedEvalEnv.getOperationArgs().addAll(currentEvalEnv.getOperationArgs());
		// point to the module we are initializing
		nestedEvalEnv.getAdapter(InternalEvaluationEnv.class).setCurrentIP(type);
		try {
			setOperationalEvaluationEnv(nestedEvalEnv);
			// push stack before a chance for exception, to have push/pop in balance 
			pushedStack(nestedEvalEnv);
	        // eventually cause STO exception
	        EvaluationUtil.checkCurrentStackDepth(currentEvalEnv);			
	       
	        // do initialization of model params here to ensure existing out extent for objects created during initialization of imported modules (fixed by bug 392080)
	        doInitModelParams(moduleInstance, modelParameters);
	        
	    	for (ModuleImport moduleImport : type.getModuleImport()) {
	    		Module importedModule = moduleImport.getImportedModule();	    		
				ModuleInstance importedInstance = moduleInstance.getThisInstanceOf(importedModule);
		    	if(importedInstance != null) { 
					ModuleInstance.Internal importedInternal = importedInstance.getAdapter(ModuleInstance.Internal.class);
					if(!importedInternal.isInitialized()) {
						initModule(importedInstance, modelParameters);
					}
	    		}
			}
	    	
	        doInitModule(moduleInstance);
	    		    	
	    	moduleInstance.getAdapter(ModuleInstance.Internal.class).setInitialized();   				
	    	
		} finally {
			setOperationalEvaluationEnv(getOperationalEvaluationEnv().getParent());
			poppedStack();
		}
    }
    
    private void doInitModelParams(ModuleInstance moduleInstance, ModelParameterHelper modelParameters) {
    	
    	if(modelParameters != null && moduleInstance.getModule().eClass() == ExpressionsPackage.eINSTANCE.getOperationalTransformation()) {
			modelParameters.initModelParameters((TransformationInstance) moduleInstance);
		}
    	
    }
    
    private void doInitModule(ModuleInstance moduleInstance) {
    	Module module = moduleInstance.getModule();
    	
        QvtOperationalEvaluationEnv env = getOperationalEvaluationEnv();
                
		for (EStructuralFeature feature : module.getConfigProperty()) {			
			Object propValue = visitConfigProperty(feature);
			env.callSetter(moduleInstance, feature, propValue, isUndefined(propValue), true);			
		}
		
        for (EStructuralFeature feature : module.getEStructuralFeatures()) {
        	if(feature instanceof ContextualProperty || module.getConfigProperty().contains(feature)) {
        		continue;
        	}

        	setCurrentEnvInstructionPointer(feature);
        	
        	OCLExpression<EClassifier> initExp = QvtOperationalParserUtil.getInitExpression(feature);
			Object propValue = null;
            if(initExp != null) {
            	propValue = visitExpression(initExp);                
            }
            else {
            	propValue = EvaluationUtil.createInitialValue(feature.getEType(), getEnvironment().getOCLStandardLibrary(), getEvaluationEnvironment());
            }
			env.callSetter(moduleInstance, feature, propValue, isUndefined(propValue), true);        
        }
        
//        for (Rename rename : module.getOwnedRenaming()) {
//            ((RenameImpl) rename).accept(getVisitor());
//        }
    }
            
	private IVirtualOperationTable getVirtualTable(EOperation operation) {
		return IVirtualOperationTable.Access.INSTANCE.getVirtualTable(operation);
	}
    
    private Object createOrGetResult(MappingOperation mappingOperation) {
        Object result = null;
        
        for (VarParameter varParam : mappingOperation.getResult()) {
        	result = getRuntimeValue(varParam.getName());
        	
        	if (isUndefined(result)) {
        		
        		if (false == varParam.getEType() instanceof VoidType<?>) {
                    result = createInstance(varParam.getEType(), ((MappingParameter) varParam).getExtent());
                    replaceInEnv(varParam.getName(), result, varParam.getEType());
                } 
        	}
        }
        
        if (mappingOperation.getResult().size() > 1) {
        	result = createTupleResult(mappingOperation);
        	replaceInEnv(Environment.RESULT_VARIABLE_NAME, result, mappingOperation.getEType());
        }
        else {
        	result = getRuntimeValue(Environment.RESULT_VARIABLE_NAME);
        }
               
        return result;
    }

    private void createOutParams(MappingOperation mappingOperation) {
        for (EParameter nextParam : mappingOperation.getEParameters()) {
            VarParameter param = (VarParameter) nextParam;
            Object paramValue = getRuntimeValue(param.getName());
            if (isUndefined(paramValue) && param.getKind() == DirectionKind.OUT) {
            	paramValue = createInstance(param.getType(), ((MappingParameter) param).getExtent());
                replaceInEnv(param.getName(), paramValue, param.getType());
            }
        }
    }
    
    private void createOutParamsDisjunct(MappingOperation operation, List<Object> argValues) {
		Iterator<EParameter> itParams = operation.getEParameters().iterator();
		Iterator<Object> itValue = argValues.iterator();
		while (itParams.hasNext()) {
			MappingParameter param = (MappingParameter) itParams.next();
			Object argValue = itValue.next();
            if (param.getKind() == DirectionKind.OUT) {
                replaceInEnv(param.getName(), argValue, param.getType());
            }
        }
    }

    private void setOutParamsValues(MappingOperation operation, List<Object> argValues) {
		Iterator<EParameter> itParams = operation.getEParameters().iterator();
		ListIterator<Object> itArgument = argValues.listIterator();
		while (itArgument.hasNext()) {
			MappingParameter mappingParam = (MappingParameter) itParams.next();
			itArgument.next();
			if (mappingParam.getKind() == DirectionKind.OUT) {
				itArgument.set(getRuntimeValue(mappingParam.getName()));
			}
		}
    }
    
    /**
     * Tag interface which represents an evaluation result which,
     * when encountered, breaks control flow.
     * 
     * Examples of this are break, continue, and return.
     */
    public static interface BreakingResult {
    	
    }
    
    /**
     * Type of result which represents the situation in which a break statement is encountered.
     */
    public static class BreakResult implements BreakingResult {
    	BreakResult() { }
    }
    
    protected final static BreakResult BREAK = new BreakResult();
    
    /**
     * Type of result which represents the situation in which a continue statement is encountered.
     */
    public static class ContinueResult implements BreakingResult {
    	ContinueResult() { }
    }
    
    protected final static ContinueResult CONTINUE = new ContinueResult();

    /**
     * The result of an operation call.
     * Represents the situation where a return statement was encountered.
     */
    public static class OperationCallResult implements BreakingResult {
    	public Object myResult;
    	public QvtOperationalEvaluationEnv myEvalEnv;
    	
		OperationCallResult(Object myResult, QvtOperationalEvaluationEnv myEvalEnv) {
			this.myResult = myResult;
			this.myEvalEnv = myEvalEnv;
		}
    }
    
    private static class MappingCallResult extends OperationCallResult {
		static final int BODY_EXECUTED = 0;
		static final int PRECOND_FAILED = 2;
		static final int FETCHED_FROM_TRACE = 4;
		static final int NO_DISJUNCT_SELECTED = 8;		
		
		int myStatus;
    	
    	private MappingCallResult(Object myResult, QvtOperationalEvaluationEnv myEvalEnv, int status) {
			super(myResult, myEvalEnv);
			myStatus = status;
		}
    	boolean isBodyExecuted() { return myStatus == BODY_EXECUTED; }
    	boolean isPreconditionFailed() { return (myStatus & PRECOND_FAILED) != 0; };
    	//boolean isFetchedFromTrace() { return (myStatus & FETCHED_FROM_TRACE) != 0; };
    	//boolean isNoDisjunctSelected() { return (myStatus & NO_DISJUCT_SELECTED) != 0; };    	
    }
    
    private OperationCallResult executeImperativeOperation(ImperativeOperation method, Object source, List<Object> args, boolean isReusingMappingCall) {    	
        QvtOperationalEvaluationEnv oldEvalEnv = getOperationalEvaluationEnv();
        
    	boolean isMapping = method instanceof MappingOperation;    	
        // eventually cause STO exception
        EvaluationUtil.checkCurrentStackDepth(oldEvalEnv);
        
        // create a nested evaluation environment for this operation call
        QvtOperationalEvaluationEnv nestedEnv = getOperationalEnv().getFactory().createEvaluationEnvironment(
        		oldEvalEnv.getContext(), oldEvalEnv);
        nestedEnv.setOperation(method);
        
        nestedEnv.getOperationArgs().addAll(args);
        if (source != getInvalid()) {
            nestedEnv.setOperationSelf(source);
        }
        
        if(isReusingMappingCall) {
        	// let the reused mapping see the reusing caller's out/result parameters
        	EvaluationUtil.mapOperationOutAndResultParams(oldEvalEnv, nestedEnv);
        }
                        
        // setup 'this' module variable  
        Module targetModule = QvtOperationalParserUtil.getOwningModule(method);
        assert targetModule != null;
        // Resolves the target module instance to call from the currently executed module 'this'
        ModuleInstance calledThisInstance = oldEvalEnv.getThisOfType(targetModule);        
        assert calledThisInstance != null;
        
        setOperationalEvaluationEnv(nestedEnv);
        // add 'this' to the nested environment
        addToEnv(QvtOperationalEnv.THIS, calledThisInstance, targetModule);        
        
        // set IP initially to the method header
        setCurrentEnvInstructionPointer(method); 

        OperationCallResult callResult = null;
        try {
        	Object result = ((ImperativeOperationImpl) method).accept(getVisitor());    	
        	assert result instanceof OperationCallResult;
        	assert !isMapping || result instanceof MappingCallResult;        	
        	
        	callResult = (OperationCallResult)result;
        }
        catch (StackOverflowError e) {
        	throwQVTException(new QvtStackOverFlowError(e));
        }
        catch (QvtRuntimeException e) {
       		throw e;
        }
        catch (RuntimeException e) {
        	String errorMessage = EvaluationMessages.QvtOperationalEvaluationVisitorImpl_unexpectedRuntimeExc;
			QvtPlugin.error(errorMessage, e);
			
        	throwQVTException(new QvtRuntimeException(errorMessage, e));
        }
        finally {
            if(isMapping && isReusingMappingCall && callResult != null) {
            	// reflect our output in the reusing mapping caller
            	if(((MappingCallResult)callResult).isBodyExecuted()) {
            		EvaluationUtil.mapOperationOutAndResultParams(nestedEnv, oldEvalEnv);
            	}
            }        	

        	setOperationalEvaluationEnv(oldEvalEnv);
        	poppedStack();
        }
        
    	return callResult;
    }
                
    private MappingCallResult dispatchDisjunctMapping(MappingOperation method) {
    	QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
    	Object source = evalEnv.getOperationSelf();
    	List<Object> args = evalEnv.getOperationArgs();
    	
    	for (MappingOperation nextDisjunct : method.getDisjunct()) {
    		
    		// consider overriding mapping (fixed by bug 309762)
    		ImperativeOperation overridingOper = EvaluationUtil.getOverridingOperation(getOperationalEvaluationEnv(), nextDisjunct);
    		if (overridingOper instanceof MappingOperation) {
    			nextDisjunct = (MappingOperation) overridingOper;
    		}
    		
    		EClassifier ctxType = QvtOperationalParserUtil.getContextualType(nextDisjunct);
    		if(ctxType != null) {
    			if(!evalEnv.isKindOf(source, nextDisjunct.getContext().getEType())) {
    				continue;
    			}
    		}
    		
    		if(!dispatchDisjunctMappingArgumentsMatch(nextDisjunct)) {
    			continue;
    		}

    		MappingCallResult result = (MappingCallResult) executeImperativeOperation(nextDisjunct, source, args, false);
    		if(!result.isPreconditionFailed()) {
    			// precondition holds, mapping either executed, fetched from trace, or disjuncted
    			result.myStatus = MappingCallResult.BODY_EXECUTED; // from disjuncting mapping consider as executed
    			
    			// add trace record for disjuncting mapping (fixed by bug 377882) 
    			replaceInEnv(Environment.RESULT_VARIABLE_NAME, result.myResult, method.getEType());
        		//retrieveOutArgs((OperationCallExp<EClassifier, EOperation>)source, result.myEvalEnv.getOperationArgs(), nextDisjunct);
    			createOutParamsDisjunct(method, result.myEvalEnv.getOperationArgs());
    			setOutParamsValues(method, args);
   			
    			TraceUtil.addTraceRecord(evalEnv, method);
    			
    			return result;
    		}
		}
    	
    	return new MappingCallResult(null, myEvalEnv, MappingCallResult.NO_DISJUNCT_SELECTED);
    }
    
    private boolean dispatchDisjunctMappingArgumentsMatch(MappingOperation disjunct) {
    	
    	List<EParameter> params = disjunct.getEParameters();
    	QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
    	List<Object> args = evalEnv.getOperationArgs();
    	    	
    	if(params.size() != args.size()) {
    		return false;
    	}
    	
    	for (int i = 0; i < args.size(); i++) {
			Object nextArg = args.get(i);
			EClassifier nextParamType = params.get(i).getEType();    			
			if(nextArg != null && !evalEnv.isKindOf(nextArg, nextParamType)) {
				return false;
			}
		}
    	
    	return true;
    	
    }
    
    protected final void throwQVTException(QvtRuntimeException exception) throws QvtRuntimeException {
		getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class)
				.throwQVTException(exception);
    }
    
	@Override
    protected Object call(EOperation operation, OCLExpression<EClassifier> body, Object target, Object[] args) {
    	if(target instanceof EObject) {
    		EObject eTarget = (EObject) target;
    		if(OCLAnnotationSupport.isDynamicInstance(eTarget)) {
    			if(operation.eClass() != eTarget.eClass()) {
    				// check if not overridden for a sub-class 
	    			EOperation actualOperation = getOCLAnnotationSupport().resolveDynamic(operation, eTarget);
	    			if(actualOperation != null && actualOperation != operation) {
	    				OCLExpression<EClassifier> actualOperBody = getOperationBody(actualOperation);
	    				
	    				if(actualOperBody != null) {
							Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> myEnv = getEnvironment();
							EnvironmentFactory<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> factory = myEnv
									.getFactory();
							// create a nested evaluation environment for this
							// operation call
							EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> nested = factory
									.createEvaluationEnvironment(getEvaluationEnvironment());
	    			    	// bind "self"
	    			    	nested.add(Environment.SELF_VARIABLE_NAME, target);	    			    	
	    			    	// add the parameter bindings to the local variables
	    			    	if (args.length > 0) {
	    			    		int i = 0;
	    			    		UMLReflection<?, ?, EOperation, ?, ?, EParameter, ?, ?, ?, ?> uml = myEnv.getUMLReflection();
	    			    		for (EParameter param : uml.getParameters(operation)) { 
	    			    			nested.add(uml.getName(param), args[i]);
	    			    		}
	    			    	}
	    			    	
							EvaluationVisitor<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> visitor = factory
									.createEvaluationVisitor(myEnv, nested, getExtentMap());
	    			    	if(visitor instanceof QvtOperationalEvaluationVisitorImpl) {
	    			    		// ensure shared instance of oclAnnotationSupport to avoid repeated OCL parsing	    			    		
	    			    		((QvtOperationalEvaluationVisitorImpl)visitor).oclAnnotationSupport = getOCLAnnotationSupport();
	    			    	}

	    			    	return visitor.visitExpression(actualOperBody);
	    				}
	    			}
    			}
    		}
    	}
    	
    	return super.call(operation, body, target, args);
    }
    
    @Override
	public Object visitCollectionLiteralExp(CollectionLiteralExp<EClassifier> cl) {
		if (cl.getType() instanceof ListType) {
			Collection<Object> result = new MutableListImpl<Object>();
			for (CollectionLiteralPart<EClassifier> part : cl.getPart()) {
				if (part instanceof CollectionItem<?>) {
					// CollectionItem part
					CollectionItem<EClassifier> item = (CollectionItem<EClassifier>) part;
					OCLExpression<EClassifier> itemExp = item.getItem();
					Object itemVal = visitExpression(itemExp);
					if (itemVal == getInvalid()) {
						return getInvalid(); // can't have an invalid element in a collection
					}
					result.add(itemVal);
				} else {
					// Collection range
					CollectionRange<EClassifier> range = (CollectionRange<EClassifier>) part;
					OCLExpression<EClassifier> first = range.getFirst();
					OCLExpression<EClassifier> last = range.getLast();

					// evaluate first value
					Object firstVal = visitExpression(first);
					Object lastVal = visitExpression(last);
					if (firstVal == getInvalid() || lastVal == getInvalid()) {
						return getInvalid(); // can't have an invalid element in a collection
					}
					if (firstVal instanceof Integer && lastVal instanceof Integer) {
						// TODO: enhance IntegerRangeList to support multiple ranges
						// add values between first and last inclusive
						int firstInt = ((Integer) firstVal).intValue();
						int lastInt = ((Integer) lastVal).intValue();
						for (int i = firstInt; i <= lastInt; i++) {
                            result.add(new Integer(i));
                        }
					}
				} // end of collection range
			} // end of parts iterator
			return result;
		}
		return super.visitCollectionLiteralExp(cl);
	}

	@Override
	protected Object navigate(EStructuralFeature property, OCLExpression<EClassifier> derivation, Object target) {
		Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> myEnv = getEnvironment();
		EnvironmentFactory<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> factory = myEnv
				.getFactory();
		// create a nested evaluation environment for this property call
		EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> nested = factory
				.createEvaluationEnvironment(getEvaluationEnvironment());
    	// bind "self"
    	nested.add(Environment.SELF_VARIABLE_NAME, target);
    	
		EvaluationVisitor<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> visitor = factory
				.createEvaluationVisitor(myEnv, nested, getExtentMap());
    	if(visitor instanceof QvtOperationalEvaluationVisitorImpl) {
    		// ensure shared instance of oclAnnotationSupport to avoid repeated OCL parsing
    		((QvtOperationalEvaluationVisitorImpl)visitor).oclAnnotationSupport = getOCLAnnotationSupport();
    	}

    	return visitor.visitExpression(derivation);
    }    

    @Override
    protected OCLExpression<EClassifier> getPropertyBody(EStructuralFeature property) {    	
    	if(OCLAnnotationSupport.isDynamicClassFeature(property)) {
    		return getOCLAnnotationSupport().getDerivedProperty(property);
    	}
    	
    	return super.getPropertyBody(property);
    }
        
	@Override
	protected OCLExpression<EClassifier> getOperationBody(EOperation operation) {
		if(operation == null) {
			return null;
		}
		
		if(OCLAnnotationSupport.isDynamicClassOperation(operation)) {			
			return getOCLAnnotationSupport().getBody(operation);
		}		
		return super.getOperationBody(operation);
	}
    
	private OCLAnnotationSupport getOCLAnnotationSupport() {
		if(oclAnnotationSupport == null) {
			oclAnnotationSupport = new OCLAnnotationSupport();		
			
			oclAnnotationSupport.setErrorHandler(new OCLAnnotationSupport.ParseErrorHandler() {
				org.eclipse.ocl.ecore.OCLExpression invalidBodyExpr = EcoreFactory.eINSTANCE.createInvalidLiteralExp();
				
				public org.eclipse.ocl.ecore.OCLExpression handleError(ParserException parserException, EModelElement contextElement) {
					QvtPlugin.error("Failed to parse OCL annotation :" +  //$NON-NLS-1$
							getUMLReflection().getQualifiedName(contextElement) , parserException);

					return invalidBodyExpr;
				}
			});
		}
		return oclAnnotationSupport;
	}
	
    protected QvtOperationalEnv getOperationalEnv() {
        return (QvtOperationalEnv) getEnvironment();
    }

    public QvtOperationalEvaluationEnv getOperationalEvaluationEnv() {
        return (QvtOperationalEvaluationEnv) getEvaluationEnvironment();
    }
    
    
	/**
	 * Adds the given variable value into evaluation environment.
	 * 
	 * @param varName
	 *            the name of the variable
	 * @param value
	 *            the value of the variable
	 * @param declaredType
	 *            the type of the variable (optional) or <code>null</code>
	 */    
	protected void addToEnv(String varName, Object value, EClassifier declaredType) {
		getOperationalEvaluationEnv().add(varName, value);
	}
	
	/**
	 * Replaces the given variable value in evaluation environment.
	 * 
	 * @param varName
	 *            the name of the variable to replace
	 * @param value
	 *            the new value of the variable
	 * @param declaredType
	 *            the type of the variable (optional) or <code>null</code>
	 */
	protected void replaceInEnv(String varName, Object value, EClassifier declaredType) {
		getOperationalEvaluationEnv().replace(varName, value);
	}
	
    private Object getRuntimeValue(final String name) {
        return getEvaluationEnvironment().getValueOf(name);
    }

    private Object getOutOwner(final ObjectExp objectExp) {
        Object owner = getRuntimeValue(objectExp.getName()); 
        if (owner != null) {
        	if (objectExp.getType() instanceof CollectionType<?, ?> == false) {
	            if (!oclIsKindOf(owner, objectExp.getType())) {
	                throw new RuntimeException(MessageFormat.format(
	                        EvaluationMessages.ExtendedOclEvaluatorVisitorImpl_InvalidObjectExpType, new Object[] {
	                                objectExp.getName(), owner, objectExp.getType() }));
	            }
        	}
        } else {
        	owner = createInstance(objectExp.getType(), (ModelParameter) objectExp.getExtent());
        	if(objectExp.getName() != null) {
        		getOperationalEvaluationEnv().replace(objectExp.getName(), owner);
        	}
        }

        return owner;
    }
    
    /**
	 * Creates tuple value representing the result of the given operation.
	 * 
	 * @param operation
	 *          the operation currently executed by this environment
	 *          
	 * @return the tuple value collecting all result parameters, never <code>null</code>
	 */
    private Tuple<EOperation, EStructuralFeature> createTupleResult(ImperativeOperation operation) {
    	boolean isMapping = operation.eClass() == ExpressionsPackage.eINSTANCE.getMappingOperation();
    	QvtOperationalEvaluationEnv evalEnv = getOperationalEvaluationEnv();
    	EList<VarParameter> resultParams = operation.getResult();
    	
    	HashMap<EStructuralFeature, Object> values = new HashMap<EStructuralFeature, Object>(2);
    	@SuppressWarnings("unchecked")
    	TupleType<EClassifier, EStructuralFeature> tupleType = (TupleType<EClassifier, EStructuralFeature>)operation.getEType();
		
    	for (EStructuralFeature tupleProp : tupleType.oclProperties()) {
			Object propVal = evalEnv.getValueOf(tupleProp.getName());
			if(propVal == null && isMapping) {
				ModelParameter extent = null;
				for (VarParameter resultParam : resultParams) {
					if(tupleProp.getName().equals(resultParam.getName())) {
						MappingParameter mappingParameter = (MappingParameter) resultParam;
						extent = mappingParameter.getExtent();
						break;
					}
				}
				
				propVal = createInstance(tupleProp.getEType(), extent);
			}
			values.put(tupleProp, propVal);
			evalEnv.replace(tupleProp.getName(), propVal, tupleProp.getEType());
		}
    	
    	return evalEnv.createTuple(operation.getEType(), values);
    }
    
	private List<Object> makeArgs(OperationCallExp<EClassifier, EOperation> operationCallExp) {
    	EOperation referredOperation = operationCallExp.getReferredOperation();
    	Iterator<EParameter> iterParam = referredOperation.getEParameters().iterator();
        List<Object> argValues = new ArrayList<Object>();
        for (OCLExpression<EClassifier> arg : operationCallExp.getArgument()) {
        	Object value = visitExpression(arg);
        	EParameter param = iterParam.next();
            argValues.add(EvaluationUtil.doImplicitListCoercion(param.getEType(), value));
        }

        return argValues;
    }
    
    private void retrieveOutArgs(OperationCallExp<EClassifier, EOperation> operationCallExp, List<Object> argValues, MappingOperation operation) {
		Iterator<OCLExpression<EClassifier>> itArgument = operationCallExp.getArgument().iterator();
		Iterator<EParameter> itParams = operation.getEParameters().iterator();
		Iterator<Object> itValue = argValues.iterator();
		while (itArgument.hasNext()) {
			OCLExpression<EClassifier> arg = itArgument.next();
			MappingParameter mappingParam = (MappingParameter) itParams.next();
			Object argValue = itValue.next();
			 
			if (mappingParam.getKind() != DirectionKind.OUT) {
				continue;
			}
			
			if (arg instanceof VariableExp<?, ?>) {
			    @SuppressWarnings("unchecked")
				VariableExp<EClassifier, EParameter> varExp = (VariableExp<EClassifier, EParameter>) arg;
			    Variable<EClassifier, EParameter> referredVariable = varExp.getReferredVariable();
			    if (referredVariable != null) {
			        String varName = referredVariable.getName();
			        EClassifier variableType = arg.getType();
			        replaceInEnv(varName, argValue, variableType);
			    }
			} else if (arg instanceof PropertyCallExp<?, ?>) {
			    Object ownerObj = getAssignExpLValueOwner(arg);
			    if (ownerObj instanceof EObject) {
			    	@SuppressWarnings("unchecked")
					PropertyCallExp<EClassifier, EStructuralFeature> propCallExp = ((PropertyCallExp<EClassifier, EStructuralFeature>) arg);
			        QvtOperationalEvaluationEnv env = getOperationalEvaluationEnv();
			        EObject oldIP = setCurrentEnvInstructionPointer(operationCallExp);
			        env.callSetter((EObject) ownerObj, propCallExp.getReferredProperty(), argValue, isUndefined(argValue), true);
			        setCurrentEnvInstructionPointer(oldIP);
			    }
			} else {
			    throw new UnsupportedOperationException("Unsupported LValue type: " + ((arg == null) ? null : arg.getType())); //$NON-NLS-1$
			}
		}
    }
    
    private List<Object> makeEntryOperationArgs(OperationalTransformation module) {
    	
    	assert !module.isIsBlackbox() : "Non-blackbox module expected";
    	
    	ImperativeOperation entryPoint = QvtOperationalParserUtil.getMainOperation(module);        
        if (entryPoint == null) {
            throw new IllegalArgumentException(NLS.bind(EvaluationMessages.ExtendedOclEvaluatorVisitorImpl_ModuleNotExecutable, module.getName()));
        }
    	
		List<Object> args = new ArrayList<Object>(entryPoint.getEParameters().size());
				
		int paramIndex = 0;
		for (EParameter param : entryPoint.getEParameters()) {
			int matchedIndex = paramIndex;

			MappingParameter mappingParam = (MappingParameter) param;
			if (mappingParam.getKind() == DirectionKind.OUT) {
				args.add(null);
				continue;
			}
			
			if (mappingParam.getExtent() != null) {
				int modelParamIndex = 0;
		        for (ModelParameter modelParam : module.getModelParameter()) {
		        	if (modelParam == mappingParam.getExtent()) {
		        		matchedIndex = modelParamIndex;
		        		break;
		        	}
		        	modelParamIndex++;
		        }
			}

	        if (matchedIndex < getOperationalEvaluationEnv().getOperationArgs().size()) {
	        	Object envArg = getOperationalEvaluationEnv().getOperationArgs().get(matchedIndex);
	        	ModelInstance argModel = (ModelInstance) envArg;
	        	ModelParameterExtent argExtent = argModel.getExtent();
				List<EObject> initialObjects = argExtent.getInitialObjects();
				if(!initialObjects.isEmpty()) {
					args.add(initialObjects.get(0));
				}
	        }
			else {
                throw new IllegalArgumentException("entry operation arguments mismatch: no argument for " + mappingParam + " parameter"); //$NON-NLS-1$ //$NON-NLS-2$
			}

	        paramIndex++;
		}
		return args;
	}
    	
	private List<Object> makeBlackboxTransformationArgs(TransformationInstance transformation, QvtOperationalEvaluationEnv evalEnv) {
		
		assert transformation.getTransformation().isIsBlackbox() : "Blackbox transformation expected";
		
		List<Object> actualArgs = new ArrayList<Object>();   	
    	
		for (ModelParameter param : EvaluationUtil.getBlackboxSignature(transformation.getTransformation())) {
			ModelInstance modelInst = transformation.getModel(param);
			Object arg = createJavaModelInstance(modelInst, evalEnv);
    		actualArgs.add(arg);
    	}
		
		for (EStructuralFeature p : transformation.getTransformation().getConfigProperty()) {
			Object val = evalEnv.navigateProperty(p, Collections.emptyList(), transformation);
			((Context) evalEnv.getContext()).setConfigProperty(p.getName(), val);
		}
    	
		return actualArgs;
	}

	private JavaModelInstance createJavaModelInstance(final ModelInstance modelInst, final QvtOperationalEvaluationEnv evalEnv) {
		return new JavaModelInstance() {
			
			final JavaModelType modelType = new JavaModelType() {
				
				public String getName() {
					return modelInst.getModelType().getName();
				}
				
				public List<EPackage> getMetamodels() {
					return modelInst.getModelType().getMetamodel();
				}
			};
			
			final JavaModelExtent modelExtent = new JavaModelExtent() {
				
				public void removeObject(EObject obj) {
					modelInst.getExtent().removeElement(obj);
				}
				
				public List<EObject> getRootObjects() {
					return modelInst.getExtent().getRootObjects();
				}
				
				public List<Object> getAllObjects() {
					return modelInst.getExtent().getAllObjects();
				}
				
				public void addObject(EObject obj) {
					modelInst.getExtent().addObject(obj);
				}
			};
			
			public JavaModelType getType() {
				return modelType;
			}
			
			public JavaModelExtent getExtent() {
				return modelExtent;
			}
		};
	}
		
	
//    private EStructuralFeature getRenamedProperty(EStructuralFeature property) {
//    	EAnnotation annotation = property.getEAnnotation(Environment.OCL_NAMESPACE_URI);
//    	if (annotation != null) {
//    		for (EObject nextAnn : annotation.getContents()) {
//    			if (false == nextAnn instanceof Constraint) {
//    				continue;
//    			}
//    			Constraint cnt = (Constraint) nextAnn;
//    			if (QvtOperationalEnv.RENAMED_PROPERTY_STEREOTYPE.equals(cnt.getStereotype())
//    					&& !cnt.getConstrainedElements().isEmpty()
//    					&& cnt.getConstrainedElements().get(0) instanceof EStructuralFeature) {
//    				return (EStructuralFeature) cnt.getConstrainedElements().get(0);
//    			}
//    		}
//    	}
//    	return property;
//    }
    
    /**
	* Wraps the environment's creatInstance() and transforms failures to QVT exception
	*/    
	protected Object createInstance(EClassifier type, ModelParameter extent) throws QvtRuntimeException {
		Object newInstance = null;
		try {			
			if(type instanceof CollectionType<?, ?>) {
				@SuppressWarnings("unchecked")
				CollectionType<EClassifier, EOperation> collectionType = (CollectionType<EClassifier, EOperation>)type;
				newInstance = EvaluationUtil.createNewCollection(collectionType);
			} else {
				newInstance = getOperationalEvaluationEnv().createInstance(type, extent);

				EFactory eFactory = type.getEPackage().getEFactoryInstance();
				if(eFactory instanceof IntermediateClassFactory) {
					IntermediateClassFactory intermFactory = (IntermediateClassFactory) eFactory;
					intermFactory.doInstancePropertyInit(newInstance, this);
				}
			}

		} catch (IllegalArgumentException e) {
			throwQVTException(new QvtRuntimeException(e));
		}
		
		return newInstance;
	}
   
    protected EObject setCurrentEnvInstructionPointer(EObject node) {
    	InternalEvaluationEnv internEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
    	if(node != null) {
    		return internEnv.setCurrentIP(node);
    	}
    	return internEnv.getCurrentIP();
    }
    
    protected InternalEvaluator createInterruptibleVisitor() {
    	final IProgressMonitor monitor = getContext().getProgressMonitor();
    	    
    	class InterruptVisitor extends QvtGenericVisitorDecorator.Any {
    		
    		public InterruptVisitor() {
    			super(QvtOperationalEvaluationVisitorImpl.this);
			}
    		
    		@Override
    		protected Object genericVisitAny(Object object) {
    			if(monitor != null && monitor.isCanceled()) {    				
    				throwQVTException(new QvtInterruptedExecutionException());    				
    			}
    			
    			// set the current instruction pointer
    			if(object instanceof EObject) {
    				InternalEvaluationEnv evalEnv = getOperationalEvaluationEnv().getAdapter(InternalEvaluationEnv.class);
    				evalEnv.setCurrentIP((EObject)object);
    			}
    			
    			return null;
    		}    		
    	};
    	
    	return new InterruptVisitor();
    }

	public OperationCallResult runMainEntry(OperationalTransformation transformation, List<Object> args) {
		ImperativeOperation entryOperation = QvtOperationalParserUtil.getMainOperation(transformation);				
				
		OperationCallResult result = executeImperativeOperation(entryOperation, null, args, false);        	        					
		processDeferredTasks();
		return result;
	}

	private void evaluateModelParameterConditions(TransformationInstance transformationInstance, QvtOperationalEvaluationEnv evalEnv) {
		for (ModelParameter parameter : transformationInstance.getTransformation().getModelParameter()) {
			if (parameter.getEType() instanceof ModelType && parameter.getKind() != DirectionKind.OUT) {
				ModelType parameterType = (ModelType) parameter.getEType();
				ModelInstance modelInstance = transformationInstance.getModel(parameter);
				for (OCLExpression<EClassifier> whereExpression : parameterType.getAdditionalCondition()) {
					myEvalEnv.add(Environment.SELF_VARIABLE_NAME, modelInstance);
					try {
						boolean isConditionMet = Boolean.TRUE.equals(visitExpression(whereExpression));
			    		if(!isConditionMet) {
			    			throwQVTException(new QvtAssertionFailed(NLS.bind(EvaluationMessages.ModelTypeConstraintFailed, 
			    					parameter.getName(), transformationInstance.getTransformation().getName())));
			    		}
					}
					finally {
						myEvalEnv.remove(Environment.SELF_VARIABLE_NAME);
					}
				}
			}
		}
	}

}
