/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Jesper Steen Moller - Bug 427089
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.eval.ExpressionBinder;
import org.eclipse.jdt.internal.debug.eval.RemoteEvaluator;
import org.eclipse.jdt.internal.debug.eval.RemoteEvaluatorBuilder;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.AndAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.AndOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAllocation;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayInitializerInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.AssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Cast;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.CompoundInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ConditionalJump;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Constructor;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.DivideAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.DivideOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Dup;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.DupX1;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.EqualEqualOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.GreaterEqualOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.GreaterOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstanceOfOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Instruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstructionSequence;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Jump;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LeftShiftAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LeftShiftOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LessEqualOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LessOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LocalVariableCreation;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MinusAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MultiplyAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MultiplyOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.NoOp;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.NotOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.OrAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.OrOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PlusAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Pop;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PostfixMinusMinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PostfixPlusPlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PrefixMinusMinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PrefixPlusPlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushArrayLength;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushArrayType;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushBoolean;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushChar;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushClassLiteralValue;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushDouble;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushFieldVariable;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushFloat;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushInt;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushLocalVariable;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushLong;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushNull;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushPrimitiveType;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushStaticFieldVariable;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushString;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushThis;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushType;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemainderAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemainderOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemoteOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ReturnInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RightShiftAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RightShiftOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.SendMessage;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.SendStaticMessage;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ThrowInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.TwiddleOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnaryMinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnaryPlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnsignedRightShiftAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnsignedRightShiftOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Value;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.XorAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.XorOperator;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.MessageFormat;

/**
 * The AST instruction compiler generates a sequence of instructions
 * (InstructionSequence) from a DOM AST.
 */
public class ASTInstructionCompiler extends ASTVisitor {

	/**
	 * Represent a break or a continue instruction. These instructions needs are
	 * stored and managed later by their related statement.
	 */
	class CompleteInstruction {
		Jump fInstruction;
		String fLabel;
		boolean fIsBreak;

		public CompleteInstruction(Jump instruction, String label,
				boolean isBreak) {
			fInstruction = instruction;
			fLabel = label;
			fIsBreak = isBreak;
		}
	}

	/**
	 * Whether to print debug messages to the console
	 */
	private static boolean VERBOSE = false;

	private InstructionSequence fInstructions;

	/**
	 * The list of pending break and continue instruction.
	 */
	private List<CompleteInstruction> fCompleteInstructions;

	private int fStartPosition;

	private boolean fActive;

	private boolean fHasErrors;

	private Stack<Instruction> fStack;

	private int fCounter;

	// internal index used to create unique variable name
	private int fUniqueIdIndex = 0;

	private IJavaProject fJavaProject;

	/**
	 * Create a new AST instruction compiler
	 */
	public ASTInstructionCompiler(int startPosition, String snippet, IJavaProject javaProject) {
		fStartPosition = startPosition;
		fInstructions = new InstructionSequence(snippet);
		fStack = new Stack<>();
		fCompleteInstructions = new ArrayList<>();
		fJavaProject = javaProject;
	}

	/**
	 * Returns the instruction sequence generated by this AST instruction
	 * compiler
	 */
	public InstructionSequence getInstructions() {
		return fInstructions;
	}

	/**
	 * Returns whether the generated instruction sequence has errors. Errors
	 * include:
	 * <ol>
	 * <li>AST contains unimplemented operations (features which will be
	 * supported, but aren't yet)</li>
	 * <li>AST contains unsupported operations (features which are not yet
	 * implemented and are likely NOT to be implemented)</li>
	 * </ol>
	 */
	public boolean hasErrors() {
		return fHasErrors;
	}

	private void setHasError(boolean value) {
		fHasErrors = value;
	}

	private void addErrorMessage(String message) {
		fInstructions.addError(message);
	}

	private boolean isActive() {
		return fActive;
	}

	private void setActive(boolean active) {
		fActive = active;
	}

	private void push(Instruction i) {
		fStack.push(i);
	}

	private void storeInstruction() {
		Instruction instruction = null;
		try {
			instruction = fStack.pop();
		}
		catch(EmptyStackException ese) {
			JDIDebugPlugin.log(new Status(
					IStatus.WARNING,
					JDIDebugPlugin.getUniqueIdentifier(),
					NLS.bind(EvaluationEngineMessages.ASTInstructionCompiler_4, fCounter),
					ese));
		}
		if(instruction != null) {
			fCounter++;
			if (instruction instanceof CompoundInstruction) {
				((CompoundInstruction) instruction).setEnd(fCounter);
			}
			fInstructions.add(instruction);
			//System.out.println("Added: " + instruction.toString()); //$NON-NLS-1$
			verbose("Add " + instruction.toString()); //$NON-NLS-1$
		}
	}

	/**
	 * Prints the given message to the console if verbose mode is on.
	 *
	 * @param message
	 *            the message to display
	 */
	private void verbose(String message) {
		if (VERBOSE) {
			System.out.println(message);
		}
	}

	private String getTypeName(ITypeBinding typeBinding) {
		if (typeBinding.isRawType()) {
			typeBinding = typeBinding.getErasure();
		}
		if (typeBinding.isTypeVariable()) {
			ITypeBinding[] typeBounds = typeBinding.getTypeBounds();
			if (typeBounds.length > 0) {
				String name = getTypeName(typeBounds[0]);
				if (typeBounds.length > 1 && "java.lang.Object".equals(name)) { //$NON-NLS-1$
					return getTypeName(typeBounds[1]);
				}
				return name;
			}
			return "java.lang.Object"; //$NON-NLS-1$
		}
		StringBuilder name;
		if (typeBinding.isArray()) {
			name = new StringBuilder(getTypeName(typeBinding.getElementType()));
			int dimensions = typeBinding.getDimensions();
			for (int i = 0; i < dimensions; i++) {
				name.append("[]"); //$NON-NLS-1$
			}
			return name.toString();
		}
		//try it the old way
		name = new StringBuilder(Signature.getTypeErasure(typeBinding.getName()));
		IPackageBinding packageBinding = typeBinding.getPackage();
		typeBinding = typeBinding.getDeclaringClass();
		while (typeBinding != null) {
			name.insert(0, '$').insert(0, Signature.getTypeErasure(typeBinding.getName()));
			typeBinding = typeBinding.getDeclaringClass();
		}
		if (packageBinding != null && !packageBinding.isUnnamed()) {
			name.insert(0, '.').insert(0, packageBinding.getName());
		}
		return name.toString();
	}

	private String getTypeSignature(ITypeBinding typeBinding) {
		return Signature.createTypeSignature(getTypeName(typeBinding), true)
				.replace('.', '/');
	}

	private boolean isALocalType(ITypeBinding typeBinding) {
		while (typeBinding != null) {
			if (typeBinding.isLocal()) {
				return true;
			}
			typeBinding = typeBinding.getDeclaringClass();
		}
		return false;
	}

	private boolean containsALocalType(IMethodBinding methodBinding) {
		ITypeBinding[] typeBindings = methodBinding.getParameterTypes();
		for (ITypeBinding typeBinding : typeBindings) {
			if (isALocalType(typeBinding)) {
				return true;
			}
		}
		return false;
	}

	private int getEnclosingLevel(ASTNode node,
			ITypeBinding referenceTypeBinding) {
		ASTNode parent = node;
		ITypeBinding refbinding = referenceTypeBinding.isParameterizedType() ? referenceTypeBinding
				.getTypeDeclaration() : referenceTypeBinding;
		do {
			parent = parent.getParent();
		} while (parent != null
				&& !(parent instanceof AbstractTypeDeclaration || parent instanceof AnonymousClassDeclaration));
		if (parent == null) {
			return 0;
		}
		ITypeBinding parentBinding = null;
		if (parent instanceof AbstractTypeDeclaration) {
			parentBinding = ((AbstractTypeDeclaration) parent).resolveBinding();
		} else if (parent instanceof AnonymousClassDeclaration) {
			parentBinding = ((AnonymousClassDeclaration) parent)
					.resolveBinding();
		}
		if (parentBinding != null
				&& (parentBinding.isEqualTo(refbinding) || parentBinding
						.isCastCompatible(refbinding))) {
			return 0;
		}
		return getEnclosingLevel(parent, referenceTypeBinding) + 1;
	}

	private int getSuperLevel(ITypeBinding current, ITypeBinding reference) {
		if (current.equals(reference)) {
			return 0;
		}
		return getSuperLevel(current.getSuperclass(), reference);
	}

	/**
	 * Return the label associated with the given statement.
	 *
	 * @param statement
	 *            the statement.
	 * @return the associated label, or <code>null</code> if there is none.
	 */
	private String getLabel(Statement statement) {
		ASTNode parent = statement.getParent();
		if (parent instanceof LabeledStatement) {
			return ((LabeledStatement) parent).getLabel().getIdentifier();
		}
		return null;
	}

	/**
	 * Append a pop instruction in the instruction list if needed. A pop
	 * instruction is added when the expression has a return value, i.e. all
	 * expressions expect method invocation expressions which have
	 * <code>void</code> as return type and variable declaration expression.
	 *
	 * @param expression
	 *            the expression to test.
	 */
	private void addPopInstructionIfNeeded(Expression expression) {
		boolean pop = true;

		if (expression instanceof MethodInvocation) {
			IMethodBinding methodBinding = (IMethodBinding) ((MethodInvocation) expression)
					.getName().resolveBinding();
			if (methodBinding != null
					&& "void".equals(methodBinding.getReturnType().getName())) { //$NON-NLS-1$
				pop = false;
			}
		} else if (expression instanceof SuperMethodInvocation) {
			IMethodBinding methodBinding = (IMethodBinding) ((SuperMethodInvocation) expression)
					.getName().resolveBinding();
			if (methodBinding != null
					&& "void".equals(methodBinding.getReturnType().getName())) { //$NON-NLS-1$
				pop = false;
			}
		} else if (expression instanceof VariableDeclarationExpression) {
			pop = false;
		}

		if (pop) {
			addPopInstruction();
		}
	}

	/**
	 *
	 */
	private void addPopInstruction() {
		Instruction lastInstruction = fInstructions
				.getInstruction(fInstructions.getEnd());
		push(new Pop(lastInstruction.getSize() + 1));
		storeInstruction();
	}

	/**
	 * Check the current type of a value and the requested type to decide if
	 * boxing/un-boxing is required. If needed, the correct instruction is added
	 * to the stack Returns true if a storeInstruction() is needed after
	 * visiting the expression
	 */
	private boolean checkAutoBoxing(ITypeBinding valueBinding,
			ITypeBinding requestedBinding) {
		if (valueBinding == null) {
			return false; // unresolved
		}
		if (valueBinding.isPrimitive() == requestedBinding.isPrimitive()) {
			return false;
		}
		if (requestedBinding.isPrimitive()) {
			unBoxing(valueBinding);
		} else {
			boxing(requestedBinding, valueBinding);
		}
		return true;
	}

	/**
	 * Add to the stack the instruction to box a primitive value.
	 */
	private void boxing(ITypeBinding requestedBinding, ITypeBinding valueBinding) {
		String requestedTypeName = requestedBinding.getQualifiedName();
		if ("java.lang.Object".equals(requestedTypeName)) { //$NON-NLS-1$
			switch (valueBinding.getBinaryName().charAt(0)) {
			case 'I':
				push(new SendStaticMessage(
						"java.lang.Integer", "valueOf", "(I)Ljava/lang/Integer;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'C':
				push(new SendStaticMessage(
						"java.lang.Character", "valueOf", "(C)Ljava/lang/Character;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'B':
				push(new SendStaticMessage(
						"java.lang.Byte", "valueOf", "(B)Ljava/lang/Byte;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'S':
				push(new SendStaticMessage(
						"java.lang.Short", "valueOf", "(S)Ljava/lang/Short;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'J':
				push(new SendStaticMessage(
						"java.lang.Long", "valueOf", "(J)Ljava/lang/Long;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'F':
				push(new SendStaticMessage(
						"java.lang.Float", "valueOf", "(F)Ljava/lang/Float;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'D':
				push(new SendStaticMessage(
						"java.lang.Double", "valueOf", "(D)Ljava/lang/Double;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'Z':
				push(new SendStaticMessage(
						"java.lang.Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			}
		} else if ("java.lang.Integer".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(I)Ljava/lang/Integer;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Character".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(C)Ljava/lang/Character;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Byte".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(B)Ljava/lang/Byte;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Short".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(S)Ljava/lang/Short;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Long".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(J)Ljava/lang/Long;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Float".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(F)Ljava/lang/Float;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Double".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(D)Ljava/lang/Double;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Boolean".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(Z)Ljava/lang/Boolean;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Add the instruction to un-box a non-primitive value if needed. Returns
	 * true if a storeInstruction() is needed after visiting the expression
	 */
	private boolean unBoxing(ITypeBinding valueBinding) {
		String valueTypeName = valueBinding.getQualifiedName();
		if ("java.lang.Integer".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("intValue", "()I", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Character".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("charValue", "()C", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Byte".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("byteValue", "()B", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Short".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("shortValue", "()S", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Long".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("longValue", "()J", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Float".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("floatValue", "()F", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Double".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("doubleValue", "()D", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Boolean".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("booleanValue", "()Z", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else {
			return false;
		}
		return true;
	}

	/**
	 * End visit methods
	 *
	 * There are two paths to ending a visit to a node:
	 * <ol>
	 * <li>For control statements, the necessary control instructions (jump,
	 * conditional jump) are inserted into the instruction sequence</li>
	 * <li>For other cases, we simply remove the node's instruction from the
	 * stack and add it to the instruction sequence.</li>
	 * </ol>
	 */

	/**
	 * @see ASTVisitor#endVisit(AnonymousClassDeclaration)
	 */
	@Override
	public void endVisit(AnonymousClassDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ArrayAccess)
	 */
	@Override
	public void endVisit(ArrayAccess node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		ITypeBinding typeBinding = node.getIndex().resolveTypeBinding();
		if (typeBinding != null && unBoxing(typeBinding)) {
			// un-box the index, if required
			storeInstruction();
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ArrayCreation)
	 */
	@Override
	public void endVisit(ArrayCreation node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ArrayInitializer)
	 */
	@Override
	public void endVisit(ArrayInitializer node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ArrayType)
	 */
	@Override
	public void endVisit(ArrayType node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(AssertStatement)
	 */
	@Override
	public void endVisit(AssertStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(Assignment)
	 */
	@Override
	public void endVisit(Assignment node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(Block)
	 */
	@Override
	public void endVisit(Block node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(BooleanLiteral)
	 */
	@Override
	public void endVisit(BooleanLiteral node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(BreakStatement)
	 */
	@Override
	public void endVisit(BreakStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(CastExpression)
	 */
	@Override
	public void endVisit(CastExpression node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(CatchClause)
	 */
	@Override
	public void endVisit(CatchClause node) {

	}

	/**
	 * @see ASTVisitor#endVisit(CharacterLiteral)
	 */
	@Override
	public void endVisit(CharacterLiteral node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ClassInstanceCreation)
	 */
	@Override
	public void endVisit(ClassInstanceCreation node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(CompilationUnit)
	 */
	@Override
	public void endVisit(CompilationUnit node) {
		while(!fStack.isEmpty()) {
			storeInstruction();
		}
	}

	/**
	 * @see ASTVisitor#endVisit(ConditionalExpression)
	 */
	@Override
	public void endVisit(ConditionalExpression node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		// Get the instructions
		int ifFalseAddress = fInstructions.getEnd();
		Instruction ifFalse = fInstructions.get(ifFalseAddress);
		int ifTrueAddress = ifFalseAddress - ifFalse.getSize();
		Instruction ifTrue = fInstructions.get(ifTrueAddress);
		int conditionalAddress = ifTrueAddress - ifTrue.getSize();

		// Insert the conditional jump
		ConditionalJump conditionalJump = new ConditionalJump(false);
		fInstructions.insert(conditionalJump, conditionalAddress + 1);

		// Insert the jump
		int jumpAddress = ifTrueAddress + 2;
		Jump jump = new Jump();
		fInstructions.insert(jump, jumpAddress);

		// Set the jump offsets
		conditionalJump.setOffset(ifTrue.getSize() + 1);
		jump.setOffset(ifFalse.getSize() + 1);

		fCounter += 2;
		storeInstruction();

	}

	/**
	 * @see ASTVisitor#endVisit(ConstructorInvocation)
	 */
	@Override
	public void endVisit(ConstructorInvocation node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ContinueStatement)
	 */
	@Override
	public void endVisit(ContinueStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(DoStatement)
	 */
	@Override
	public void endVisit(DoStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		/*
		 * The structure of generated instructions is :
		 *
		 * -- | body -- -- |condition -- - jump to the first instruction of the
		 * body if the condition is true.
		 */

		String label = getLabel(node);

		// get address of each part
		int conditionAddress = fInstructions.getEnd();
		Instruction condition = fInstructions.getInstruction(conditionAddress);
		int bodyAddress = conditionAddress - condition.getSize();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int bodyStartAddress = bodyAddress - body.getSize();

		// add the conditionnalJump
		ConditionalJump conditionalJump = new ConditionalJump(true);
		fInstructions.add(conditionalJump);
		fCounter++;

		// set jump offsets
		conditionalJump.setOffset(-(condition.getSize() + body.getSize() + 1));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > bodyStartAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((conditionAddress - instructionAddress) + 1);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset(bodyAddress - instructionAddress);
				}
			}
		}

		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(EmptyStatement)
	 */
	@Override
	public void endVisit(EmptyStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom
	 * .EnhancedForStatement)
	 */
	@Override
	public void endVisit(EnhancedForStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		/*
		 * The structure of generated instructions is :
		 *
		 * For an array: -- | <ParameterType>[] a= Expression | int i= 0 |
		 * <ParameterType> <ParameterName> -- -- | i < a.length - jump to the
		 * instruction after the last jump if the condition is false. -- -- | s=
		 * a[i] | Body -- -- - jump to the first instruction of the condition.
		 *
		 * For an Iterable: -- | Iterator i= Expression.iterator() |
		 * <ParameterType> <ParameterName> -- -- | i.hasNext() - jump to the
		 * instruction after the last jump if the condition is false. -- -- | s=
		 * i.next() | Body -- -- - jump to the first instruction of the
		 * condition.
		 */

		int bodyAddress = fInstructions.getEnd();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int conditionAddress = bodyAddress - body.getSize();
		Instruction condition = fInstructions.getInstruction(conditionAddress);
		int initAddress = conditionAddress - condition.getSize();

		// add conditional jump
		ConditionalJump condJump = new ConditionalJump(false);
		fInstructions.insert(condJump, conditionAddress + 1);
		bodyAddress++;
		fCounter++;
		condJump.setOffset(body.getSize() + 1);

		// add jump
		Jump jump = new Jump();
		fInstructions.add(jump);
		fCounter++;
		jump.setOffset(initAddress - (bodyAddress + 1));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		String label = getLabel(node);
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > conditionAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((bodyAddress - instructionAddress) + 1);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset(initAddress - instructionAddress);
				}
			}
		}

		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ExpressionStatement)
	 */
	@Override
	public void endVisit(ExpressionStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		addPopInstructionIfNeeded(node.getExpression());
	}

	/**
	 * @see ASTVisitor#endVisit(FieldAccess)
	 */
	@Override
	public void endVisit(FieldAccess node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(FieldDeclaration)
	 */
	@Override
	public void endVisit(FieldDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ForStatement)
	 */
	@Override
	public void endVisit(ForStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		/*
		 * The structure of generated instructions is :
		 *
		 * -- |initialization -- -- |condition -- - jump to the instruction
		 * after the last jump if the condition is false. -- | body -- -- |
		 * updaters -- - jump to the first instruction of the condition.
		 */

		String label = getLabel(node);
		boolean hasCondition = node.getExpression() != null;

		// get address of each part
		int updatersAddress = fInstructions.getEnd();
		Instruction updaters = fInstructions.getInstruction(updatersAddress);
		int bodyAddress = updatersAddress - updaters.getSize();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int bodyStartAddress = bodyAddress - body.getSize();

		int conditionAddress;
		Instruction condition;

		if (hasCondition) {
			conditionAddress = bodyStartAddress;
			condition = fInstructions.getInstruction(conditionAddress);
		} else {
			conditionAddress = 0;
			condition = null;
		}

		// add jump
		Jump jump = new Jump();
		fInstructions.add(jump);
		fCounter++;

		if (hasCondition) {
			// add conditional jump
			ConditionalJump condJump = new ConditionalJump(false);
			fInstructions.insert(condJump, conditionAddress + 1);
			bodyAddress++;
			bodyStartAddress++;
			updatersAddress++;
			fCounter++;
			// set conditional jump offset
			condJump.setOffset(body.getSize() + updaters.getSize() + 1);
		}

		// set jump offset
		jump.setOffset(-((hasCondition && (condition != null) ? condition
				.getSize() : 0) + body.getSize() + updaters.getSize() + 2));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > bodyStartAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((updatersAddress - instructionAddress) + 1);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset(bodyAddress - instructionAddress);
				}
			}
		}

		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(IfStatement)
	 */
	@Override
	public void endVisit(IfStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		boolean hasElseStatement = node.getElseStatement() != null;

		// Get the instructions

		int ifFalseAddress = 0;
		Instruction ifFalse = null;
		int ifTrueAddress = 0;
		Instruction ifTrue = null;

		if (hasElseStatement) {
			ifFalseAddress = fInstructions.getEnd();
			ifFalse = fInstructions.get(ifFalseAddress);
			ifTrueAddress = ifFalseAddress - ifFalse.getSize();
			ifTrue = fInstructions.get(ifTrueAddress);
		} else {
			ifTrueAddress = fInstructions.getEnd();
			ifTrue = fInstructions.get(ifTrueAddress);
		}

		int conditionalAddress = ifTrueAddress - ifTrue.getSize();

		// Insert the conditional jump
		ConditionalJump conditionalJump = new ConditionalJump(false);
		fInstructions.insert(conditionalJump, conditionalAddress + 1);
		// Set the jump offset
		conditionalJump.setOffset(ifTrue.getSize()
				+ ((hasElseStatement) ? 1 : 0));
		fCounter++;

		if (hasElseStatement) {
			// Insert the jump
			int jumpAddress = ifTrueAddress + 2;
			Jump jump = new Jump();
			fInstructions.insert(jump, jumpAddress);
			// Set the jump offset
			jump.setOffset(ifFalse.getSize() + 1);
			fCounter++;
		}

		storeInstruction();

	}

	/**
	 * @see ASTVisitor#endVisit(ImportDeclaration)
	 */
	@Override
	public void endVisit(ImportDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(InfixExpression)
	 */
	@Override
	public void endVisit(InfixExpression node) {
	}

	/**
	 * @see ASTVisitor#endVisit(Initializer)
	 */
	@Override
	public void endVisit(Initializer node) {

	}

	/**
	 * @see ASTVisitor#endVisit(InstanceofExpression)
	 */
	@Override
	public void endVisit(InstanceofExpression node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(Javadoc)
	 */
	@Override
	public void endVisit(Javadoc node) {

	}

	/**
	 * @see ASTVisitor#endVisit(LabeledStatement)
	 */
	@Override
	public void endVisit(LabeledStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		String label = node.getLabel().getIdentifier();

		// for each pending continue instruction which are related to
		// this statement, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			if (instruction.fLabel != null && instruction.fLabel.equals(label)) {
				iter.remove();
				Jump jumpInstruction = instruction.fInstruction;
				int instructionAddress = fInstructions.indexOf(jumpInstruction);
				if (instruction.fIsBreak) {
					// jump to the instruction after the statement
					jumpInstruction.setOffset(fInstructions.getEnd()
							- instructionAddress);
				}
			}
		}
	}

	/**
	 * @see ASTVisitor#endVisit(MethodDeclaration)
	 */
	@Override
	public void endVisit(MethodDeclaration node) {
		setActive(false);
	}

	/**
	 * @see ASTVisitor#endVisit(MethodInvocation)
	 */
	@Override
	public void endVisit(MethodInvocation node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(NullLiteral)
	 */
	@Override
	public void endVisit(NullLiteral node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(NumberLiteral)
	 */
	@Override
	public void endVisit(NumberLiteral node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(PackageDeclaration)
	 */
	@Override
	public void endVisit(PackageDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(SimpleType)
	 */
	@Override
	public void endVisit(ParameterizedType node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ParenthesizedExpression)
	 */
	@Override
	public void endVisit(ParenthesizedExpression node) {

	}

	/**
	 * @see ASTVisitor#endVisit(PostfixExpression)
	 */
	@Override
	public void endVisit(PostfixExpression node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(PrefixExpression)
	 */
	@Override
	public void endVisit(PrefixExpression node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(PrimitiveType)
	 */
	@Override
	public void endVisit(PrimitiveType node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(QualifiedName)
	 */
	@Override
	public void endVisit(QualifiedName node) {
	}

	/**
	 * @see ASTVisitor#endVisit(SimpleType)
	 */
	@Override
	public void endVisit(QualifiedType node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ReturnStatement)
	 */
	@Override
	public void endVisit(ReturnStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SimpleName)
	 */
	@Override
	public void endVisit(SimpleName node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SimpleType)
	 */
	@Override
	public void endVisit(SimpleType node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SingleVariableDeclaration)
	 */
	@Override
	public void endVisit(SingleVariableDeclaration node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(StringLiteral)
	 */
	@Override
	public void endVisit(StringLiteral node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	@Override
	public void endVisit(TextBlock node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SuperConstructorInvocation)
	 */
	@Override
	public void endVisit(SuperConstructorInvocation node) {

	}

	/**
	 * @see ASTVisitor#endVisit(SuperFieldAccess)
	 */
	@Override
	public void endVisit(SuperFieldAccess node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SuperMethodInvocation)
	 */
	@Override
	public void endVisit(SuperMethodInvocation node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SwitchCase)
	 */
	@Override
	public void endVisit(SwitchCase node) {
		// never called
	}

	/**
	 * @see ASTVisitor#endVisit(SwitchStatement)
	 */
	@Override
	public void endVisit(SwitchStatement node) {
		// nothing to do
	}

	/**
	 * @see ASTVisitor#endVisit(SynchronizedStatement)
	 */
	@Override
	public void endVisit(SynchronizedStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ThisExpression)
	 */
	@Override
	public void endVisit(ThisExpression node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ThrowStatement)
	 */
	@Override
	public void endVisit(ThrowStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(TryStatement)
	 */
	@Override
	public void endVisit(TryStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(TypeDeclaration)
	 */
	@Override
	public void endVisit(TypeDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(TypeDeclarationStatement)
	 */
	@Override
	public void endVisit(TypeDeclarationStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(TypeLiteral)
	 */
	@Override
	public void endVisit(TypeLiteral node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(VariableDeclarationExpression)
	 */
	@Override
	public void endVisit(VariableDeclarationExpression node) {

	}

	/**
	 * @see ASTVisitor#endVisit(VariableDeclarationFragment)
	 */
	@Override
	public void endVisit(VariableDeclarationFragment node) {
		if (!isActive() || hasErrors()) {
			return;
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(VariableDeclarationStatement)
	 */
	@Override
	public void endVisit(VariableDeclarationStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(WhileStatement)
	 */
	@Override
	public void endVisit(WhileStatement node) {
		if (!isActive() || hasErrors()) {
			return;
		}

		/*
		 * The structure of generated instructions is :
		 *
		 * -- |condition -- - jump to the instruction after the last jump if the
		 * condition is false. -- | body -- - jump to the first instruction of
		 * the condition.
		 */

		String label = getLabel(node);

		// get address of each part
		int bodyAddress = fInstructions.getEnd();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int conditionAddress = bodyAddress - body.getSize();
		Instruction condition = fInstructions.getInstruction(conditionAddress);

		// add the conditionnalJump
		ConditionalJump conditionalJump = new ConditionalJump(false);
		fInstructions.insert(conditionalJump, conditionAddress + 1);

		// add the jump
		Jump jump = new Jump();
		fInstructions.add(jump);

		// set jump offsets
		conditionalJump.setOffset(body.getSize() + 1);
		jump.setOffset(-(condition.getSize() + body.getSize() + 2));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > conditionAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((bodyAddress - instructionAddress) + 2);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset((conditionAddress - condition
							.getSize()) - instructionAddress);
				}
			}
		}

		fCounter += 2;
		storeInstruction();
	}

	/*
	 * Visit methods
	 *
	 * There are two variations of node visiting: <ol> <li>Push the instruction
	 * corresponding to the node onto the stack and return <code>true</code> to
	 * visit the children of the node.</li> <li>Push the instruction
	 * corresponding to the node onto the stack and visit the children of the
	 * node manually (return <code>false</code> to avoid the default child
	 * visiting implementation).</li> </ol>
	 */

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * AnnotationTypeDeclaration)
	 */
	@Override
	public boolean visit(AnnotationTypeDeclaration node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * AnnotationTypeMemberDeclaration)
	 */
	@Override
	public boolean visit(AnnotationTypeMemberDeclaration node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(AnonymousClassDeclaration)
	 */
	@Override
	public boolean visit(AnonymousClassDeclaration node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Anonymous_type_declaration_cannot_be_used_in_an_evaluation_expression_2);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ArrayAccess)
	 */
	@Override
	public boolean visit(ArrayAccess node) {
		if (!isActive()) {
			return false;
		}

		push(new org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAccess(
				fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ArrayCreation)
	 */
	@Override
	public boolean visit(ArrayCreation node) {
		if (!isActive()) {
			return false;
		}

		ArrayType arrayType = node.getType();

		ITypeBinding binding = resolveTypeBinding(arrayType);
		if (binding != null && isALocalType(binding.getElementType())) {
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Local_type_array_instance_creation_cannot_be_used_in_an_evaluation_expression_29);
			setHasError(true);
			return false;
		}

		push(new ArrayAllocation(arrayType.getDimensions(), node.dimensions()
				.size(), node.getInitializer() != null, fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ArrayInitializer)
	 */
	@Override
	public boolean visit(ArrayInitializer node) {
		if (!isActive()) {
			return false;
		}

		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			int dimension = typeBinding.getDimensions();
			String signature = getTypeSignature(typeBinding.getElementType());
			push(new ArrayInitializerInstruction(signature, node.expressions()
					.size(), dimension, fCounter));
		}

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ArrayType)
	 */
	@Override
	public boolean visit(ArrayType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding arrayTypeBinding = resolveTypeBinding(node);
		if (arrayTypeBinding != null) {
			int dimension = arrayTypeBinding.getDimensions();
			String signature = getTypeSignature(arrayTypeBinding
					.getElementType());
			push(new PushArrayType(signature, dimension, fCounter));
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(AssertStatement)
	 */
	@Override
	public boolean visit(AssertStatement node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Assert_statement_cannot_be_used_in_an_evaluation_expression_3);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(Assignment)
	 */
	@Override
	public boolean visit(Assignment node) {
		if (!isActive()) {
			return false;
		}
		Expression leftHandSide = node.getLeftHandSide();
		Expression rightHandSide = node.getRightHandSide();
		int variableTypeId = getTypeId(leftHandSide);
		int valueTypeId = getTypeId(rightHandSide);

		String opToken = node.getOperator().toString();
		int opTokenLength = opToken.length();
		char char0 = opToken.charAt(0);
		char char2 = '\0';
		if (opTokenLength > 2) {
			char2 = opToken.charAt(2);
		}

		ITypeBinding rightBinding = resolveTypeBinding(rightHandSide);
		if (rightBinding == null) {
			return false;
		}
		ITypeBinding leftBinding = resolveTypeBinding(leftHandSide);
		if (leftBinding == null) {
			return false;
		}
		if (variableTypeId == Instruction.T_Object) {
			// If the variable is an object, the value may need to be boxed for
			// the simple assignment.
			// For the compound assignment operators, the value of the variable
			// have to be un-boxed before the operation is done, then re-boxed
			// to
			// to be stored in the variable.

			int unboxedVariableTypeId = getUnBoxedTypeId(leftHandSide);
			int unboxedValueTypeId = getUnBoxedTypeId(rightHandSide);
			int unboxedResultTypeId = Instruction.getBinaryPromotionType(
					unboxedVariableTypeId, unboxedValueTypeId);

			push(new AssignmentOperator(variableTypeId, variableTypeId,
					fCounter));

			leftHandSide.accept(this);

			if (char0 == '=') {

				boolean storeRequired = false;
				if (rightBinding.isPrimitive()) {
					boxing(leftBinding, rightBinding);
					storeRequired = true;
				}
				rightHandSide.accept(this);
				if (storeRequired) {
					storeInstruction(); // boxing
				}

			} else {
				boolean unrecognized = false;

				boxing(leftBinding, rightBinding);

				switch (char0) {
				case '=': // equal
					break;
				case '+': // plus equal
					push(new PlusOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '-': // minus equal
					push(new MinusOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '*': // multiply equal
					push(new MultiplyOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '/': // divide equal
					push(new DivideOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '%': // remainder equal
					push(new RemainderOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '^': // XOr equal
					push(new XorOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '|': // or equal
					push(new OrOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '&': // and equal
					push(new AndOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '<': // left shift equal
					push(new LeftShiftOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '>': // right shift equal or unsigned right shift equal
					switch (char2) {
					case '=': // right shift equal
						push(new RightShiftOperator(unboxedVariableTypeId,
								unboxedValueTypeId, unboxedResultTypeId,
								fCounter));
						break;
					case '>': // unsigned right shift equal
						push(new UnsignedRightShiftOperator(
								unboxedVariableTypeId, unboxedValueTypeId,
								unboxedResultTypeId, fCounter));
						break;
					default:
						unrecognized = true;
						break;
					}
					break;
				default:
					unrecognized = true;
					break;
				}

				if (unrecognized) {
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_assignment_operator____4
							+ opToken);
					return false;
				}

				unBoxing(leftBinding);
				push(new Dup());
				storeInstruction(); // dupe
				storeInstruction(); // un-boxing

				boolean storeRequired = unBoxing(rightBinding);
				rightHandSide.accept(this);
				if (storeRequired) {
					storeInstruction(); // un-boxing
				}

				storeInstruction(); // operation
				storeInstruction(); // boxing

			}

		} else {
			boolean unrecognized = false;

			switch (char0) {
			case '=': // equal
				push(new AssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '+': // plus equal
				push(new PlusAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '-': // minus equal
				push(new MinusAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '*': // multiply equal
				push(new MultiplyAssignmentOperator(variableTypeId,
						valueTypeId, fCounter));
				break;
			case '/': // divide equal
				push(new DivideAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '%': // remainder equal
				push(new RemainderAssignmentOperator(variableTypeId,
						valueTypeId, fCounter));
				break;
			case '^': // XOr equal
				push(new XorAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '|': // or equal
				push(new OrAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '&': // and equal
				push(new AndAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '<': // left shift equal
				push(new LeftShiftAssignmentOperator(variableTypeId,
						valueTypeId, fCounter));
				break;
			case '>': // right shift equal or unsigned right shift equal
				switch (char2) {
				case '=': // right shift equal
					push(new RightShiftAssignmentOperator(variableTypeId,
							valueTypeId, fCounter));
					break;
				case '>': // unsigned right shift equal
					push(new UnsignedRightShiftAssignmentOperator(
							variableTypeId, valueTypeId, fCounter));
					break;
				default:
					unrecognized = true;
					break;
				}
				break;
			default:
				unrecognized = true;
				break;
			}

			if (unrecognized) {
				setHasError(true);
				addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_assignment_operator____4
						+ opToken);
				return false;
			}

			leftHandSide.accept(this);
			boolean storeRequired = unBoxing(rightBinding);
			rightHandSide.accept(this);
			if (storeRequired) {
				storeInstruction();
			}
		}

		return false;

	}

	/**
	 * @see ASTVisitor#visit(Block)
	 */
	@Override
	public boolean visit(Block node) {
		int start = node.getStartPosition();
		if (start == fStartPosition || start == (fStartPosition + 1)) {
			setActive(true);
		}
		if (!isActive()) {
			return true;
		}

		push(new NoOp(fCounter));

		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * BlockComment)
	 */
	@Override
	public boolean visit(BlockComment node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(BooleanLiteral)
	 */
	@Override
	public boolean visit(BooleanLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushBoolean(node.booleanValue()));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(BreakStatement)
	 */
	@Override
	public boolean visit(BreakStatement node) {
		if (!isActive()) {
			return false;
		}
		// create the equivalent jump instruction in the instruction
		// and add an element in the list of pending break and continue
		// instructions
		Jump instruction = new Jump();
		SimpleName labelName = node.getLabel();
		String label = null;
		if (labelName != null) {
			label = labelName.getIdentifier();
		}
		push(instruction);
		fCompleteInstructions.add(new CompleteInstruction(instruction, label,
				true));

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CastExpression)
	 */
	@Override
	public boolean visit(CastExpression node) {
		if (!isActive()) {
			return false;
		}

		Type type = node.getType();
		int typeId = getTypeId(type);
		ITypeBinding typeBinding = resolveTypeBinding(type);

		if (typeBinding != null) {
			String baseTypeSignature;
			int dimension = typeBinding.getDimensions();
			if (typeBinding.isArray()) {
				typeBinding = typeBinding.getElementType();
			}
			baseTypeSignature = getTypeName(typeBinding);
			push(new Cast(typeId, baseTypeSignature, dimension, fCounter));
			node.getExpression().accept(this);
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CatchClause)
	 */
	@Override
	public boolean visit(CatchClause node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Catch_clause_cannot_be_used_in_an_evaluation_expression_6);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(CharacterLiteral)
	 */
	@Override
	public boolean visit(CharacterLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushChar(node.charValue()));

		return true;
	}

	/**
	 * return false, visit expression, type name & arguments, don't visit body
	 * declaration
	 *
	 * @see ASTVisitor#visit(ClassInstanceCreation)
	 */
	@Override
	public boolean visit(ClassInstanceCreation node) {
		if (!isActive()) {
			return true;
		}

		if (node.getAnonymousClassDeclaration() != null) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Anonymous_type_declaration_cannot_be_used_in_an_evaluation_expression_7);
		}

		IMethodBinding methodBinding = node.resolveConstructorBinding();
		if (methodBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_1,
					new Object[] { node.toString() }));
			return false;
		}
		ITypeBinding typeBinding = methodBinding.getDeclaringClass();

		boolean isInstanceMemberType = typeBinding.isMember()
				&& !Modifier.isStatic(typeBinding.getModifiers());

		if (isALocalType(typeBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Constructor_of_a_local_type_cannot_be_used_in_an_evaluation_expression_8);
		}

		if (containsALocalType(methodBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Constructor_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_30);
		}

		if (hasErrors()) {
			return false;
		}

		int paramCount = methodBinding.getParameterTypes().length;

		String enclosingTypeSignature = null;
		ITypeBinding enclosingTypeBinding = null;
		if (isInstanceMemberType) {
			enclosingTypeBinding = typeBinding.getDeclaringClass();
			if (enclosingTypeBinding == null) {
				setHasError(true);
				addErrorMessage(MessageFormat.format(
						EvaluationEngineMessages.ASTInstructionCompiler_2,
						new Object[] { typeBinding.getQualifiedName() }));
				return false;
			}
			enclosingTypeSignature = getTypeSignature(enclosingTypeBinding);
			paramCount++;
		}

		String signature = getMethodSignature(methodBinding,
				enclosingTypeSignature).replace('.', '/');

		push(new Constructor(signature, paramCount, fCounter));

		push(new PushType(getTypeName(typeBinding)));
		storeInstruction();

		if (isInstanceMemberType) {
			Expression optionalExpression = node.getExpression();
			if (optionalExpression != null) {
				optionalExpression.accept(this);
			} else {
				// for a non-static inner class, check if we are not in a static
				// context (method)
				ASTNode parent = node;
				do {
					parent = parent.getParent();
				} while (!(parent instanceof MethodDeclaration));
				if (Modifier.isStatic(((MethodDeclaration) parent)
						.getModifiers())) {
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Must_explicitly_qualify_the_allocation_with_an_instance_of_the_enclosing_type_33);
					return false;
				}

				push(new PushThis(getEnclosingLevel(node, enclosingTypeBinding)));
				storeInstruction();
			}
		}

		List<Expression> arguments = node.arguments();
		pushMethodArguments(methodBinding, arguments);

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CompilationUnit)
	 */
	@Override
	public boolean visit(CompilationUnit node) {
		return true;
	}

	/**
	 * @see ASTVisitor#visit(ConditionalExpression)
	 */
	@Override
	public boolean visit(ConditionalExpression node) {
		if (!isActive()) {
			return true;
		}

		push(new NoOp(fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ConstructorInvocation)
	 */
	@Override
	public boolean visit(ConstructorInvocation node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_this_constructor_invocation_cannot_be_used_in_an_evaluation_expression_9);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ContinueStatement)
	 */
	@Override
	public boolean visit(ContinueStatement node) {
		if (!isActive()) {
			return false;
		}
		// create the equivalent jump instruction in the instruction
		// and add an element in the list of pending break and continue
		// instructions
		Jump instruction = new Jump();
		SimpleName labelName = node.getLabel();
		String label = null;
		if (labelName != null) {
			label = labelName.getIdentifier();
		}
		push(instruction);
		fCompleteInstructions.add(new CompleteInstruction(instruction, label,
				false));

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CreationReference)
	 */
	@Override
	public boolean visit(CreationReference node) {
		if (!isActive()) {
			return true;
		}
		try {
			RemoteEvaluatorBuilder builder = makeBuilder(node);
			builder.acceptMethodReference(node, node.resolveTypeBinding());
			RemoteEvaluator remoteEvaluator = builder.build();
			push(new RemoteOperator(builder.getSnippet(), node.getStartPosition(), remoteEvaluator));
			storeInstruction();
		} catch (JavaModelException | DebugException e) {
			addErrorMessage(e.getMessage());
			setHasError(true);
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(DoStatement)
	 */
	@Override
	public boolean visit(DoStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(EmptyStatement)
	 */
	@Override
	public boolean visit(EmptyStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new NoOp(fCounter));
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * EnhancedForStatement)
	 */
	@Override
	public boolean visit(EnhancedForStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));

		ITypeBinding typeBinding = resolveTypeBinding(node.getExpression());
		if (typeBinding == null) {
			return false;
		}
		Type paramType = node.getParameter().getType();
		ITypeBinding paramBinding = resolveTypeBinding(paramType);
		if (paramBinding == null) {
			return false;
		}
		String typeSignature = getTypeSignature(paramBinding);
		int paramTypeId = getTypeId(paramType);
		boolean isParamPrimitiveType = paramTypeId != Instruction.T_Object
				&& paramTypeId != Instruction.T_String;
		String paramIdentifier = node.getParameter().getName().getIdentifier();

		if (typeBinding.isArray()) {
			// the expression returns an array
			int idIndex = fUniqueIdIndex++;
			String arrayIdentifier = "#a" + idIndex; //$NON-NLS-1$
			String varIdentifier = "#i" + idIndex; //$NON-NLS-1$
			push(new LocalVariableCreation(arrayIdentifier, typeSignature, 1,
					isParamPrimitiveType, true, fCounter));
			node.getExpression().accept(this);
			storeInstruction();
			push(new LocalVariableCreation(varIdentifier,
					"I", 0, true, true, fCounter)); //$NON-NLS-1$
			push(new PushInt(0));
			storeInstruction();
			storeInstruction();
			push(new LocalVariableCreation(paramIdentifier, typeSignature, 0,
					isParamPrimitiveType, false, fCounter));
			storeInstruction();

			push(new LessOperator(Instruction.T_int, Instruction.T_int,
					fCounter));
			push(new PushLocalVariable(varIdentifier));
			storeInstruction();
			push(new PushArrayLength(fCounter));
			push(new PushLocalVariable(arrayIdentifier));
			storeInstruction();
			storeInstruction();
			storeInstruction();

			// conditional jump will be added here

			push(new NoOp(fCounter));
			push(new AssignmentOperator(paramTypeId, paramTypeId, fCounter));
			push(new PushLocalVariable(paramIdentifier));
			storeInstruction();
			push(new org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAccess(
					fCounter));
			push(new PushLocalVariable(arrayIdentifier));
			storeInstruction();
			push(new PostfixPlusPlusOperator(Instruction.T_int, fCounter));
			push(new PushLocalVariable(varIdentifier));
			storeInstruction();
			storeInstruction();
			storeInstruction();
			if (checkAutoBoxing(typeBinding.getElementType(), paramBinding)) {
				storeInstruction();
			}
			storeInstruction();
			addPopInstruction();
			node.getBody().accept(this);
			storeInstruction();

			// jump will be added here

		} else {
			// the expression returns a collection
			String iteratorIdentifier = "#i" + fUniqueIdIndex++; //$NON-NLS-1$
			push(new LocalVariableCreation(iteratorIdentifier,
					"Ljava/util/Iterator;", 0, false, true, fCounter)); //$NON-NLS-1$
			push(new SendMessage(
					"iterator", "()Ljava/util/Iterator;", 0, null, fCounter)); //$NON-NLS-1$//$NON-NLS-2$
			node.getExpression().accept(this);
			storeInstruction();
			storeInstruction();
			push(new LocalVariableCreation(paramIdentifier, typeSignature, 0,
					isParamPrimitiveType, false, fCounter));
			storeInstruction();

			push(new SendMessage("hasNext", "()Z", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
			push(new PushLocalVariable(iteratorIdentifier));
			storeInstruction();
			storeInstruction();

			// conditional jump will be added here

			push(new NoOp(fCounter));
			push(new AssignmentOperator(paramTypeId, paramTypeId, fCounter));
			push(new PushLocalVariable(paramIdentifier));
			storeInstruction();
			push(new SendMessage(
					"next", "()Ljava/lang/Object;", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
			push(new PushLocalVariable(iteratorIdentifier));
			storeInstruction();
			storeInstruction();
			ITypeBinding[] typeArguments = typeBinding.getTypeArguments();
			if (typeArguments != null && typeArguments.length > 0) {
				if (checkAutoBoxing(typeArguments[0], paramBinding)) {
					storeInstruction();
				}
			}
			storeInstruction();
			addPopInstruction();
			node.getBody().accept(this);
			storeInstruction();

			// jump will be added here

		}

		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * EnumConstantDeclaration)
	 */
	@Override
	public boolean visit(EnumConstantDeclaration node) {
		if (!isActive()) {
			return true;
		}

		// nothing to do, we shouldn't hit this node
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * EnumDeclaration)
	 */
	@Override
	public boolean visit(EnumDeclaration node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_0);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ExpressionMethodReference)
	 */
	@Override
	public boolean visit(ExpressionMethodReference node) {
		if (!isActive()) {
			return true;
		}

		try {
			RemoteEvaluatorBuilder builder = makeBuilder(node);
			builder.acceptMethodReference(node, node.resolveTypeBinding());
			RemoteEvaluator remoteEvaluator = builder.build();
			push(new RemoteOperator(builder.getSnippet(), node.getStartPosition(), remoteEvaluator));
			storeInstruction();
		} catch (JavaModelException | DebugException e) {
			addErrorMessage(e.getMessage());
			setHasError(true);
		}

		return false;
	}

	private RemoteEvaluatorBuilder makeBuilder(ASTNode node) throws DebugException {
		RemoteEvaluatorBuilder builder = new RemoteEvaluatorBuilder(fJavaProject, new ExpressionBinder() {
			@Override
			public void bind(IVariableBinding variableBinding, String asVariableName) {
				String variableId = variableBinding.getName();
				push(new PushLocalVariable(variableId));
				storeInstruction();
			}

			@Override
			public void bindThis(ITypeBinding typeBinding, String asVariableName) {
				push(new PushThis(getEnclosingLevel(node, typeBinding)));
				storeInstruction();
			}

		}, getEnclosingClass(node), isStaticContext(node), false);
		return builder;
	}

	private ITypeBinding getEnclosingClass(ASTNode node) {
		while (node != null) {
			if (node instanceof MethodDeclaration) {
				return ((MethodDeclaration) node).resolveBinding().getDeclaringClass();
			}
			if (node instanceof TypeDeclaration) {
				return ((TypeDeclaration) node).resolveBinding();
			}
			node = node.getParent();
		}
		return null;
	}

	private boolean isStaticContext(ASTNode node) {
		while (node != null) {
			if (node instanceof MethodDeclaration) {
				return Modifier.isStatic(((MethodDeclaration) node).getModifiers());
			} else if (node instanceof Initializer) {
				return Modifier.isStatic(((Initializer) node).getModifiers());
			}
			node = node.getParent();
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ExpressionStatement)
	 */
	@Override
	public boolean visit(ExpressionStatement node) {
		return true;
	}

	/**
	 * return false, visit expression, don't visit name
	 *
	 * @see ASTVisitor#visit(FieldAccess)
	 */
	@Override
	public boolean visit(FieldAccess node) {
		if (!isActive()) {
			return false;
		}

		SimpleName fieldName = node.getName();
		IVariableBinding fieldBinding = (IVariableBinding) fieldName
				.resolveBinding();
		if (fieldBinding != null) {
			ITypeBinding declaringTypeBinding = fieldBinding
					.getDeclaringClass();
			Expression expression = node.getExpression();
			String fieldId = fieldName.getIdentifier();

			if (Modifier.isStatic(fieldBinding.getModifiers())) {
				push(new PushStaticFieldVariable(fieldId,
						getTypeName(declaringTypeBinding), fCounter));
				expression.accept(this);
				addPopInstruction();
			} else {
				if (declaringTypeBinding == null) { // it is a field without
													// declaring type => it is
													// the special length array
													// field
					push(new PushArrayLength(fCounter));
				} else {
					if (isALocalType(declaringTypeBinding)) {
						setHasError(true);
						addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Qualified_local_type_field_access_cannot_be_used_in_an_evaluation_expression_31);
						return false;
					}
					push(new PushFieldVariable(fieldId,
							getTypeSignature(declaringTypeBinding), fCounter));
				}
				expression.accept(this);
			}
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(FieldDeclaration)
	 */
	@Override
	public boolean visit(FieldDeclaration node) {
		return true;
	}

	/**
	 * @see ASTVisitor#visit(ForStatement) return <code>false</code>, don't use
	 *      the standard accept order. order used for visiting children :
	 *      initializers, condition, body, updaters
	 */
	@Override
	public boolean visit(ForStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));

		push(new NoOp(fCounter));
		for (Iterator<Expression> iter = node.initializers().iterator(); iter.hasNext();) {
			Expression expr = iter.next();
			expr.accept(this);
			addPopInstructionIfNeeded(expr);
		}
		storeInstruction();

		Expression condition = node.getExpression();
		if (condition != null) {
			condition.accept(this);
		}

		node.getBody().accept(this);

		push(new NoOp(fCounter));
		for (Iterator<Expression> iter = node.updaters().iterator(); iter.hasNext();) {
			Expression expr = iter.next();
			expr.accept(this);
			addPopInstructionIfNeeded(expr);
		}
		storeInstruction();

		return false;
	}

	/**
	 * @see ASTVisitor#visit(IfStatement)
	 */
	@Override
	public boolean visit(IfStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ImportDeclaration)
	 */
	@Override
	public boolean visit(ImportDeclaration node) {
		return false;
	}

	/**
	 * return <code>false</code>, don't use the standard accept order.
	 *
	 * @see ASTVisitor#visit(InfixExpression)
	 */
	@Override
	public boolean visit(InfixExpression node) {
		if (!isActive()) {
			return false;
		}

		String opToken = node.getOperator().toString();
		int opTokenLength = opToken.length();
		char char0 = opToken.charAt(0);
		char char1 = '\0';
		char char2 = '\0';
		if (opTokenLength > 1) {
			char1 = opToken.charAt(1);
			if (opTokenLength > 2) {
				char2 = opToken.charAt(2);
			}
		}

		List<Expression> extendedOperands = node.extendedOperands();

		int operatorNumber = extendedOperands.size() + 1;

		int[][] types = new int[operatorNumber][3];

		Iterator<Expression> iterator = extendedOperands.iterator();

		Expression leftOperand = node.getLeftOperand();
		Expression rightOperand = node.getRightOperand();
		int leftTypeId;
		int rightTypeId;
		boolean unbox = false;
		// for == and != un-box when at least operand is primitive (otherwise
		// compare the objects)
		ITypeBinding leftBinding = resolveTypeBinding(leftOperand);
		if (leftBinding == null) {
			return false;
		}
		ITypeBinding rightBinding = resolveTypeBinding(rightOperand);
		if (rightBinding == null) {
			return false;
		}
		if ((char0 == '=' || char0 == '!') && char1 == '=') {
			unbox = leftBinding.isPrimitive() || rightBinding.isPrimitive();
		} else {
			unbox = true;
		}
		if (unbox) {
			leftTypeId = getUnBoxedTypeId(leftOperand);
			rightTypeId = getUnBoxedTypeId(rightOperand);
		} else {
			leftTypeId = getTypeId(leftOperand);
			rightTypeId = getTypeId(rightOperand);
		}
		int resultTypeId = Instruction.getBinaryPromotionType(leftTypeId,
				rightTypeId);

		types[0][0] = resultTypeId;
		types[0][1] = leftTypeId;
		types[0][2] = rightTypeId;

		for (int i = 1; i < operatorNumber; i++) {
			Expression operand = iterator.next();
			leftTypeId = resultTypeId;
			rightTypeId = getUnBoxedTypeId(operand);
			resultTypeId = Instruction.getBinaryPromotionType(leftTypeId,
					rightTypeId);
			types[i][0] = resultTypeId;
			types[i][1] = leftTypeId;
			types[i][2] = rightTypeId;
		}

		boolean unrecognized = false;

		switch (char0) {
		case '*': // multiply
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new MultiplyOperator(types[i][0], types[i][1],
						types[i][2], fCounter));
			}
			break;
		case '/': // divide
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new DivideOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '%': // remainder
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new RemainderOperator(types[i][0], types[i][1],
						types[i][2], fCounter));
			}
			break;
		case '+': // plus
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new PlusOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '-': // minus
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new MinusOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '<': // left shift or less or less equal
			switch (char1) {
			case '\0': // less
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new LessOperator(types[i][1], types[i][2], fCounter));
				}
				break;
			case '<': // left shift
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new LeftShiftOperator(
							Instruction.getUnaryPromotionType(types[i][1]),
							types[i][1], types[i][2], fCounter));
				}
				break;
			case '=': // less equal
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new LessEqualOperator(types[i][1], types[i][2],
							fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '>': // right shift or unsigned right shift or greater or greater
					// equal
			switch (char1) {
			case '\0': // greater
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new GreaterOperator(types[i][1], types[i][2], fCounter));
				}
				break;
			case '>': // right shift or unsigned right shift
				switch (char2) {
				case '\0': // right shift
					for (int i = operatorNumber - 1; i >= 0; i--) {
						push(new RightShiftOperator(
								Instruction.getUnaryPromotionType(types[i][1]),
								types[i][1], types[i][2], fCounter));
					}
					break;
				case '>': // unsigned right shift
					for (int i = operatorNumber - 1; i >= 0; i--) {
						push(new UnsignedRightShiftOperator(
								Instruction.getUnaryPromotionType(types[i][1]),
								types[i][1], types[i][2], fCounter));
					}
					break;
				}
				break;
			case '=': // greater equal
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new GreaterEqualOperator(types[i][1], types[i][2],
							fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '=': // equal equal
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new EqualEqualOperator(types[i][1], types[i][2], true,
						fCounter));
			}
			break;
		case '!': // not equal
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new EqualEqualOperator(types[i][1], types[i][2], false,
						fCounter));
			}
			break;
		case '^': // XOr
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new XorOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '|': // or or or or
			switch (char1) {
			case '\0': // or
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new OrOperator(types[i][0], types[i][1], types[i][2],
							fCounter));
				}
				break;
			case '|': // or or
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new NoOp(fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '&': // and or and and
			switch (char1) {
			case '\0': // and
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new AndOperator(types[i][0], types[i][1], types[i][2],
							fCounter));
				}
				break;
			case '&': // and and
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new NoOp(fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		default:
			unrecognized = true;
			break;
		}
		if (unrecognized) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_infix_operator____13
					+ opToken);
		}
		if (hasErrors()) {
			return false;
		}

		iterator = extendedOperands.iterator();

		if ((char0 == '&' && char1 == '&') || (char0 == '|' && char1 == '|')) {
			boolean isOrOr = char0 == '|';

			ConditionalJump[] conditionalJumps = new ConditionalJump[operatorNumber];
			int[] conditionalJumpAddresses = new int[operatorNumber];

			boolean storeRequired = unBoxing(leftBinding);
			leftOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}

			ConditionalJump conditionalJump = new ConditionalJump(isOrOr);
			conditionalJumps[0] = conditionalJump;
			conditionalJumpAddresses[0] = fCounter;
			push(conditionalJump);
			storeInstruction();

			storeRequired = unBoxing(rightBinding);
			rightOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}

			for (int i = 1; i < operatorNumber; i++) {
				conditionalJump = new ConditionalJump(isOrOr);
				conditionalJumps[i] = conditionalJump;
				conditionalJumpAddresses[i] = fCounter;
				push(conditionalJump);
				storeInstruction();
				Expression operand = iterator.next();
				ITypeBinding typeBinding = resolveTypeBinding(operand);
				if (typeBinding == null) {
					return false;
				}
				storeRequired = unBoxing(typeBinding);
				operand.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}

			Jump jump = new Jump();
			jump.setOffset(1);
			push(jump);
			storeInstruction();

			for (int i = 0; i < operatorNumber; i++) {
				conditionalJumps[i].setOffset(fCounter
						- conditionalJumpAddresses[i] - 1);
			}

			push(new PushBoolean(isOrOr));
			storeInstruction();

			// store the no-op
			storeInstruction();

		} else { // other operators

			boolean storeRequired = false;
			if (unbox) {
				storeRequired = unBoxing(leftBinding);
			}
			leftOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}
			if (unbox) {
				storeRequired = unBoxing(rightBinding);
			}
			rightOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}

			storeInstruction();
			for (int i = 1; i < operatorNumber; i++) {
				Expression operand = iterator.next();
				if (unbox) {
					ITypeBinding typeBinding = resolveTypeBinding(operand);
					if (typeBinding == null) {
						return false;
					}
					storeRequired = unBoxing(typeBinding);
				}
				operand.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
				storeInstruction();
			}
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(Initializer)
	 */
	@Override
	public boolean visit(Initializer node) {
		return true;
	}

	/**
	 * @see ASTVisitor#visit(InstanceofExpression)
	 */
	@Override
	public boolean visit(InstanceofExpression node) {
		if (!isActive()) {
			return false;
		}
		push(new InstanceOfOperator(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(Javadoc)
	 */
	@Override
	public boolean visit(Javadoc node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(LabeledStatement) return <code>false</code>, don't
	 *      use the standard accept order.
	 */
	@Override
	public boolean visit(LabeledStatement node) {
		node.getBody().accept(this);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(LambdaExpression)
	 */
	@Override
	public boolean visit(LambdaExpression node) {
		if (!isActive()) {
			return true;
		}

		try {
			RemoteEvaluatorBuilder builder = makeBuilder(node);
			builder.acceptLambda(node, node.resolveTypeBinding());
			RemoteEvaluator remoteEvaluator = builder.build();
			push(new RemoteOperator(builder.getSnippet(), node.getStartPosition(), remoteEvaluator));
			storeInstruction();
		} catch (JavaModelException | DebugException e) {
			addErrorMessage(e.getMessage());
			setHasError(true);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * LineComment)
	 */
	@Override
	public boolean visit(LineComment node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * MarkerAnnotation)
	 */
	@Override
	public boolean visit(MarkerAnnotation node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef
	 * )
	 */
	@Override
	public boolean visit(MemberRef node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * MemberValuePair)
	 */
	@Override
	public boolean visit(MemberValuePair node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(MethodDeclaration)
	 */
	@Override
	public boolean visit(MethodDeclaration node) {
		int start = node.getStartPosition();
		int end = start + node.getLength();
		if (start < fStartPosition && end > fStartPosition) {
			return true;
		}
		return false;
	}

	/**
	 * return false, don't visit name, visit expression & arguments
	 *
	 * @see ASTVisitor#visit(MethodInvocation)
	 */
	@Override
	public boolean visit(MethodInvocation node) {
		if (!isActive()) {
			return false;
		}

		IMethodBinding methodBinding = (IMethodBinding) node.getName().resolveBinding();
		if (methodBinding == null) {
			// could be the receiver is not visible - for example a private
			// field access from super class
			ASTNode root = node.getRoot();
			if (root instanceof CompilationUnit) {
				CompilationUnit cu = (CompilationUnit) root;
				IProblem[] problems = cu.getProblems();
				for (IProblem problem : problems) {
					setHasError(true);
					addErrorMessage(problem.getMessage());
				}
			}
		}

		if (hasErrors()) {
			return false;
		}

		if (containsALocalType(methodBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Method_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_32);
			return false;
		}

		int paramCount = methodBinding.getParameterTypes().length;
		String selector = methodBinding.getName();

		String signature = getMethodSignature(methodBinding, null).replace('.',
				'/');

		boolean isStatic = Flags.isStatic(methodBinding.getModifiers());
		Expression expression = node.getExpression();

		if (isStatic) {
			String typeName = getTypeName(methodBinding.getDeclaringClass());
			push(new SendStaticMessage(typeName, selector, signature,
					paramCount, fCounter));
			if (expression != null) {
				node.getExpression().accept(this);
				addPopInstruction();
			}
		} else {
			push(new SendMessage(selector, signature, paramCount, null,
					fCounter));
			if (expression == null) {
				push(new PushThis(getEnclosingLevel(node,
						methodBinding.getDeclaringClass())));
				storeInstruction();
			} else {
				node.getExpression().accept(this);
			}
		}

		List<Expression> arguments = node.arguments();
		pushMethodArguments(methodBinding, arguments);

		return false;
	}

	/**
	 * Pushes method arguments onto the stack for a method or constructor
	 * invocation taking variable arguments and auto-boxing into consideration.
	 *
	 * @param methodBinding
	 *            method or constructor being called
	 * @param arguments
	 *            argument list
	 */
	private void pushMethodArguments(IMethodBinding methodBinding, List<Expression> arguments) {
		int argCount = arguments.size();
		ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
		int paramCount = parameterTypes.length;
		ITypeBinding lastArgBinding = null;
		if (methodBinding.isVarargs()) {
			Expression lastArg = arguments.get(argCount - 1);
			lastArgBinding = resolveTypeBinding(lastArg);
			if (lastArgBinding == null) {
				return;
			}
		}
		if (methodBinding.isVarargs() &&
				!(paramCount == argCount &&
				parameterTypes[paramCount - 1].getDimensions() == lastArgBinding.getDimensions())) {
			// if this method is a varargs, and if the method is invoked using
			// the varargs syntax
			// (multiple arguments) and not an array
			Iterator<Expression> iterator = arguments.iterator();
			// process the first arguments (no part of the variable argument)
			for (int i = 0; i < paramCount - 1; i++) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			// create a array of the remainder arguments
			ITypeBinding varargsParameterType = parameterTypes[paramCount - 1];
			ITypeBinding varargsElementType = varargsParameterType
					.getElementType();
			push(new ArrayInitializerInstruction(
					getTypeSignature(varargsElementType), argCount - paramCount
							+ 1, varargsParameterType.getDimensions(), fCounter));
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), varargsElementType);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			storeInstruction();
		} else {
			Iterator<Expression> iterator = arguments.iterator();
			int i = 0;
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i++]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef
	 * )
	 */
	@Override
	public boolean visit(MethodRef node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * MethodRefParameter)
	 */
	@Override
	public boolean visit(MethodRefParameter node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier
	 * )
	 */
	@Override
	public boolean visit(Modifier node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * NormalAnnotation)
	 */
	@Override
	public boolean visit(NormalAnnotation node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(NullLiteral)
	 */
	@Override
	public boolean visit(NullLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushNull());

		return true;
	}

	/**
	 * @see ASTVisitor#visit(NumberLiteral)
	 */
	@Override
	public boolean visit(NumberLiteral node) {
		if (!isActive()) {
			return false;
		}

		int literalType = getTypeId(node);
		String token = node.getToken();
		int tokenLastCharOffset = token.length() - 1;
		char lastChar = token.charAt(tokenLastCharOffset);
		String subToken = token.substring(0, tokenLastCharOffset);

		switch (literalType) {
		case Instruction.T_byte:
			push(new PushInt(parseByteValue(token)));
			break;
		case Instruction.T_short:
			push(new PushInt(parseShortValue(token)));
			break;
		case Instruction.T_int:
			push(new PushInt(parseIntValue(token)));
			break;
		case Instruction.T_long:
			push(new PushLong(parseLongValue(subToken)));
			break;
		case Instruction.T_float:
			push(new PushFloat(
					Float.parseFloat(removePrefixZerosAndUnderscores(subToken,
							false))));
			break;
		case Instruction.T_double:
			if (lastChar == 'D' || lastChar == 'd') {
				push(new PushDouble(
						Double.parseDouble(removePrefixZerosAndUnderscores(
								subToken, false))));
			} else {
				push(new PushDouble(
						Double.parseDouble(removePrefixZerosAndUnderscores(
								token, false))));
			}
			break;
		}

		return true;
	}

	/**
	 * Removes all preamble typing and underscores and returns the base integer
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the int value of the token
	 */
	public static int parseIntValue(String token) {
		token = removePrefixZerosAndUnderscores(token, false);
		switch (getBase(token)) {
		case 8:
			return Integer.valueOf(token.substring(1), 8).intValue();
		case 16:
			return Integer.valueOf(token.substring(2), 16).intValue();
		case 2:
			return Integer.valueOf(token.substring(2), 2).intValue();
		default:
			return Integer.valueOf(token, 10).intValue();
		}
	}

	/**
	 * Removes all preamble typing and underscores and returns the base short
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the short value of the token
	 */
	public static short parseShortValue(String token) {
		token = removePrefixZerosAndUnderscores(token, false);
		switch (getBase(token)) {
		case 8:
			return Short.valueOf(token.substring(1), 8).shortValue();
		case 16:
			return Short.valueOf(token.substring(2), 16).shortValue();
		case 2:
			return Short.valueOf(token.substring(2), 2).shortValue();
		default:
			return Short.valueOf(token, 10).shortValue();
		}
	}

	/**
	 * Removes all preamble typing and underscores and returns the base byte
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the byte value of the token
	 */
	public static byte parseByteValue(String token) {
		token = removePrefixZerosAndUnderscores(token, false);
		switch (getBase(token)) {
		case 8:
			return Byte.valueOf(token.substring(1), 8).byteValue();
		case 16:
			return Byte.valueOf(token.substring(2), 16).byteValue();
		case 2:
			return Byte.valueOf(token.substring(2), 2).byteValue();
		default:
			return Byte.valueOf(token, 10).byteValue();
		}
	}

	/**
	 * Removes all preamble typing and underscores and returns the base long
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the long value of the token
	 */
	public static long parseLongValue(String token) {
		token = removePrefixZerosAndUnderscores(token, true);
		switch (getBase(token)) {
		case 8:
			return Long.valueOf(token.substring(1), 8).longValue();
		case 16:
			return Long.valueOf(token.substring(2), 16).longValue();
		case 2:
			return Long.valueOf(token.substring(2), 2).longValue();
		default:
			return Long.valueOf(token, 10).longValue();
		}
	}

	/**
	 * Returns the numeric base for the given token according to the Java
	 * specification. Returns 8, 10, or 16.
	 *
	 * @param token
	 *            the token to get the base from
	 * @return the numeric base for the given token
	 */
	public static int getBase(String token) {
		if (token.charAt(0) == '0' && (token.length() > 1)) {
			switch (token.charAt(1)) {
			case 'x':
			case 'X':
				// "0x" prefix: Hexadecimal
				return 16;
			case 'b':
			case 'B':
				// "0b" prefix: binary
				return 2;
			default:
				// "0" prefix: Octal
				return 8;
			}
		}
		return 10; // No prefix: Decimal
	}

	/**
	 * @see ASTVisitor#visit(PackageDeclaration)
	 */
	@Override
	public boolean visit(PackageDeclaration node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * ParameterizedType)
	 */
	@Override
	public boolean visit(ParameterizedType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushType(getTypeName(typeBinding)));
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ParenthesizedExpression)
	 */
	@Override
	public boolean visit(ParenthesizedExpression node) {
		if (!isActive()) {
			return false;
		}
		return true;
	}

	/**
	 * @see ASTVisitor#visit(PostfixExpression)
	 */
	@Override
	public boolean visit(PostfixExpression node) {
		if (!isActive()) {
			return false;
		}

		Expression operand = node.getOperand();
		int expressionTypeId = getTypeId(operand);

		String opToken = node.getOperator().toString();
		char char0 = opToken.charAt(0);

		if (expressionTypeId == Instruction.T_Object) {

			int expressionUnBoxedTypeId = getUnBoxedTypeId(operand);

			AssignmentOperator assignmentInstruction = new AssignmentOperator(
					Instruction.T_Object, Instruction.T_Object, fCounter);
			push(assignmentInstruction);
			operand.accept(this);
			switch (char0) {
			case '+': // plus plus
				push(new PlusOperator(expressionUnBoxedTypeId,
						expressionUnBoxedTypeId, expressionUnBoxedTypeId,
						fCounter));
				break;
			case '-': // minus minus
				push(new MinusOperator(expressionUnBoxedTypeId,
						expressionUnBoxedTypeId, expressionUnBoxedTypeId,
						fCounter));
				break;
			default:
				setHasError(true);
				addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_postfix_operator____15
						+ opToken);
				return false;
			}
			push(new Value(fCounter));
			push(new Dup());
			storeInstruction(); // dupe
			storeInstruction(); // value
			push(new DupX1());
			storeInstruction(); // dup_x1
			ITypeBinding typeBinding = resolveTypeBinding(operand);
			if (typeBinding == null) {
				return false;
			}
			unBoxing(typeBinding);
			storeInstruction(); // un-boxing
			push(new PushInt(1));
			storeInstruction(); // push 1
			storeInstruction(); // operator
			boxing(typeBinding, null);
			storeInstruction(); // boxing
			storeInstruction(); // assignment
			push(new Pop(assignmentInstruction.getSize() + 1));

			return false;
		}

		switch (char0) {
		case '+': // plus plus
			push(new PostfixPlusPlusOperator(expressionTypeId, fCounter));
			break;
		case '-': // minus minus
			push(new PostfixMinusMinusOperator(expressionTypeId, fCounter));
			break;
		default:
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_postfix_operator____15
					+ opToken);
			return false;
		}

		return true;
	}

	/**
	 * @see ASTVisitor#visit(PrefixExpression)
	 */
	@Override
	public boolean visit(PrefixExpression node) {
		if (!isActive()) {
			return false;
		}

		Expression operand = node.getOperand();
		int expressionTypeId = getTypeId(operand);

		String opToken = node.getOperator().toString();
		int opTokenLength = opToken.length();
		char char0 = opToken.charAt(0);
		char char1 = '\0';
		if (opTokenLength > 1) {
			char1 = opToken.charAt(1);
		}

		boolean unrecognized = false;

		if (expressionTypeId == Instruction.T_Object) {

			int expressionUnBoxedTypeId = getUnBoxedTypeId(operand);

			ITypeBinding typeBinding = resolveTypeBinding(operand);
			if (typeBinding == null) {
				return false;
			}
			if (char1 == '\0') {
				switch (char0) {
				case '+': // unary plus
					push(new UnaryPlusOperator(expressionUnBoxedTypeId,
							fCounter));
					break;
				case '-': // unary minus
					push(new UnaryMinusOperator(expressionUnBoxedTypeId,
							fCounter));
					break;
				case '~': // twiddle
					push(new TwiddleOperator(expressionUnBoxedTypeId, fCounter));
					break;
				case '!': // not
					push(new NotOperator(expressionUnBoxedTypeId, fCounter));
					break;
				default:
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16
							+ opToken);
					return false;
				}

				unBoxing(typeBinding);
				operand.accept(this);
				storeInstruction(); // un-boxing

			} else {
				// plus plus and minus minus operators

				push(new AssignmentOperator(Instruction.T_Object,
						Instruction.T_Object, fCounter));

				operand.accept(this);

				boxing(typeBinding, null);

				switch (char1) {
				case '+':
					push(new PlusOperator(expressionUnBoxedTypeId,
							expressionUnBoxedTypeId, expressionUnBoxedTypeId,
							fCounter));
					break;
				case '-':
					push(new MinusOperator(expressionUnBoxedTypeId,
							expressionUnBoxedTypeId, expressionUnBoxedTypeId,
							fCounter));
					break;
				default:
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16
							+ opToken);
					return false;
				}

				unBoxing(typeBinding);
				push(new Dup());
				storeInstruction(); // dupe
				storeInstruction(); // un-boxing
				push(new PushInt(1));
				storeInstruction(); // push 1

				storeInstruction(); // operator
				storeInstruction(); // boxing

			}

			return false;
		}

		switch (char0) {
		case '+': // plus plus or unary plus
			switch (char1) {
			case '\0': // unary plus
				push(new UnaryPlusOperator(expressionTypeId, fCounter));
				break;
			case '+': // plus plus
				push(new PrefixPlusPlusOperator(expressionTypeId, fCounter));
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '-': // minus minus or unary minus
			switch (char1) {
			case '\0': // unary minus
				push(new UnaryMinusOperator(expressionTypeId, fCounter));
				break;
			case '-': // minus minus
				push(new PrefixMinusMinusOperator(expressionTypeId, fCounter));
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '~': // twiddle
			push(new TwiddleOperator(expressionTypeId, fCounter));
			break;
		case '!': // not
			push(new NotOperator(expressionTypeId, fCounter));
			break;
		default:
			unrecognized = true;
			break;
		}

		if (unrecognized) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16
					+ opToken);
			return false;
		}

		return true;
	}

	/**
	 * @see ASTVisitor#visit(PrimitiveType)
	 */
	@Override
	public boolean visit(PrimitiveType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushPrimitiveType(getTypeName(typeBinding)));
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(QualifiedName)
	 */
	@Override
	public boolean visit(QualifiedName node) {
		if (!isActive()) {
			return false;
		}

		if (hasErrors()) {
			return true;
		}

		IBinding binding = resolveBinding(node);
		if (binding == null) {
			return false;
		}
		switch (binding.getKind()) {
		case IBinding.TYPE:
			node.getName().accept(this);
			break;
		case IBinding.VARIABLE:
			SimpleName fieldName = node.getName();
			IVariableBinding fieldBinding = (IVariableBinding) resolveBinding(fieldName);
			if (fieldBinding == null) {
				return false;
			}
			ITypeBinding declaringTypeBinding = fieldBinding
					.getDeclaringClass();
			String fieldId = fieldName.getIdentifier();

			if (Modifier.isStatic(fieldBinding.getModifiers())) {
				push(new PushStaticFieldVariable(fieldId,
						getTypeName(declaringTypeBinding), fCounter));
			} else {
				if (declaringTypeBinding == null) {
					push(new PushArrayLength(fCounter));
				} else {
					push(new PushFieldVariable(fieldId,
							getTypeSignature(declaringTypeBinding), fCounter));
				}
				node.getQualifier().accept(this);
			}
			storeInstruction();
			break;
		}

		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * QualifiedType)
	 */
	@Override
	public boolean visit(QualifiedType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushType(getTypeName(typeBinding)));
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ReturnStatement)
	 */
	@Override
	public boolean visit(ReturnStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new ReturnInstruction(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(SimpleName)
	 */
	@Override
	public boolean visit(SimpleName node) {
		if (!isActive()) {
			return false;
		}

		if (hasErrors()) {
			return true;
		}

		IBinding binding = resolveBinding(node);
		if (binding == null) {
			return true;
		}
		String variableId = node.getIdentifier();

		switch (binding.getKind()) {
		case IBinding.TYPE:
			ITypeBinding typeBinding = (ITypeBinding) binding;
			push(new PushType(getTypeName(typeBinding)));
			break;
		case IBinding.VARIABLE:
			IVariableBinding variableBinding = (IVariableBinding) binding;
			ITypeBinding declaringTypeBinding = variableBinding
					.getDeclaringClass();
			if (variableBinding.isField()) {
				if (Modifier.isStatic(variableBinding.getModifiers())) {
					push(new PushStaticFieldVariable(variableId,
							getTypeName(declaringTypeBinding), fCounter));
				} else {
					push(new PushFieldVariable(variableId,
							getTypeSignature(declaringTypeBinding), fCounter));
					push(new PushThis(getEnclosingLevel(node,
							declaringTypeBinding)));
					storeInstruction();
				}
			} else {
				push(new PushLocalVariable(variableId));
			}
			break;
		}
		return true;
	}

	/**
	 * return false, don't visit child
	 *
	 * @see ASTVisitor#visit(SimpleType)
	 */
	@Override
	public boolean visit(SimpleType node) {
		if (!isActive()) {
			return false;
		}

		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushType(getTypeName(typeBinding)));
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * SingleMemberAnnotation)
	 */
	@Override
	public boolean visit(SingleMemberAnnotation node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SingleVariableDeclaration) return
	 *      <code>false</code>, don't use the standard accept order.
	 */
	@Override
	public boolean visit(SingleVariableDeclaration node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node.getType());
		if (typeBinding != null) {
			int typeDimension = typeBinding.getDimensions();
			if (typeDimension != 0) {
				typeBinding = typeBinding.getElementType();
			}
			Expression initializer = node.getInitializer();
			push(new LocalVariableCreation(node.getName().getIdentifier(),
					getTypeSignature(typeBinding), typeDimension,
					typeBinding.isPrimitive(), initializer != null, fCounter));
			if (initializer != null) {
				initializer.accept(this);
			}
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(StringLiteral)
	 */
	@Override
	public boolean visit(StringLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushString(node.getLiteralValue()));

		return true;
	}

	@Override
	public boolean visit(TextBlock node) {
		if (!isActive()) {
			return false;
		}

		push(new PushString(node.getLiteralValue()));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(SuperConstructorInvocation)
	 */
	@Override
	public boolean visit(SuperConstructorInvocation node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_super_constructor_invocation_cannot_be_used_in_an_evaluation_expression_19);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SuperFieldAccess)
	 */
	@Override
	public boolean visit(SuperFieldAccess node) {
		if (!isActive()) {
			return false;
		}

		SimpleName fieldName = node.getName();
		IVariableBinding fieldBinding = (IVariableBinding) resolveBinding(fieldName);
		if (fieldBinding == null) {
			return false;
		}
		ITypeBinding declaringTypeBinding = fieldBinding.getDeclaringClass();
		String fieldId = fieldName.getIdentifier();

		if (Modifier.isStatic(fieldBinding.getModifiers())) {
			push(new PushStaticFieldVariable(fieldId,
					getTypeName(declaringTypeBinding), fCounter));
		} else {
			Name qualifier = node.getQualifier();
			int superLevel = 1;
			int enclosingLevel = 0;
			if (qualifier != null) {
				ITypeBinding typeBinding = resolveTypeBinding(qualifier);
				if (typeBinding == null) {
					return false;
				}
				superLevel = getSuperLevel(typeBinding, declaringTypeBinding);
				ITypeBinding binding = (ITypeBinding) resolveBinding(qualifier);
				if (binding == null) {
					return false;
				}
				enclosingLevel = getEnclosingLevel(node, binding);
			}
			push(new PushFieldVariable(fieldId, superLevel, fCounter));
			push(new PushThis(enclosingLevel));
			storeInstruction();
		}

		return false;
	}

	/**
	 * return false, don't visit name, visit arguments
	 *
	 * @see ASTVisitor#visit(SuperMethodInvocation)
	 */
	@Override
	public boolean visit(SuperMethodInvocation node) {
		if (!isActive()) {
			return false;
		}

		IMethodBinding methodBinding = (IMethodBinding) resolveBinding(node
				.getName());
		if (methodBinding == null) {
			return false;
		}

		if (containsALocalType(methodBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Method_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_32);
			return false;
		}

		ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
		int paramCount = parameterTypes.length;
		String selector = methodBinding.getName();
		String signature = getMethodSignature(methodBinding, null);

		Name qualifier = node.getQualifier();
		if (Modifier.isStatic(methodBinding.getModifiers())) {
			push(new SendStaticMessage(
					getTypeName(methodBinding.getDeclaringClass()), selector,
					signature, paramCount, fCounter));
		} else {
			push(new SendMessage(selector, signature, paramCount,
					getTypeSignature(methodBinding.getDeclaringClass()),
					fCounter));
			int enclosingLevel = 0;
			if (qualifier != null) {
				ITypeBinding typeBinding = (ITypeBinding) resolveBinding(qualifier);
				if (typeBinding == null) {
					return false;
				}
				enclosingLevel = getEnclosingLevel(node, typeBinding);
			}
			push(new PushThis(enclosingLevel));
			storeInstruction();
		}

		List<Expression> arguments = node.arguments();
		int argCount = arguments.size();
		ITypeBinding lastArgBinding = null;
		if (methodBinding.isVarargs()) {
			lastArgBinding = resolveTypeBinding(arguments.get(argCount - 1));
			if (lastArgBinding == null) {
				return false;
			}
		}
		if (methodBinding.isVarargs() &&
				!(paramCount == argCount &&
				parameterTypes[paramCount - 1].getDimensions() == lastArgBinding.getDimensions())) {
			// if this method is a varargs, and if the method is invoked using
			// the varargs syntax
			// (multiple arguments) and not an array
			Iterator<Expression> iterator = arguments.iterator();
			// process the first arguments (no part of the variable argument)
			for (int i = 0; i < paramCount - 1; i++) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			// create a array of the remainder arguments
			ITypeBinding varargsParameterType = parameterTypes[paramCount - 1];
			ITypeBinding varargsElementType = varargsParameterType
					.getElementType();
			push(new ArrayInitializerInstruction(
					getTypeSignature(varargsElementType), argCount - paramCount
							+ 1, varargsParameterType.getDimensions(), fCounter));
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), varargsElementType);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			storeInstruction();
		} else {
			Iterator<Expression> iterator = arguments.iterator();
			int i = 0;
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i++]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(SuperMethodReference)
	 */
	@Override
	public boolean visit(SuperMethodReference node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Reference_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}

	@Override
	public boolean visit(SwitchExpression node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Switch_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SwitchCase)
	 */
	@Override
	public boolean visit(SwitchCase node) {
		// never called
		return false;
	}

	class slot {
		ArrayList<ConditionalJump> jumps = new ArrayList<>();
		ArrayList<Statement> stmts = null;
	}

	/**
	 * @see ASTVisitor#visit(SwitchStatement)
	 */
	@SuppressWarnings("deprecation")
	@Override
	public boolean visit(SwitchStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new NoOp(fCounter));
		int switchStart = fCounter;
		node.getExpression().accept(this);

		ArrayList<Statement> statementsDefault = null;
		Jump jumpDefault = null;
		ArrayList<slot> jumpsStatements = new ArrayList<>();
		slot currentslot = new slot();
		jumpsStatements.add(currentslot);

		for (Iterator<Statement> iter = node.statements().iterator(); iter.hasNext();) {
			Statement statement = iter.next();
			if (statement instanceof SwitchCase) {
				SwitchCase switchCase = (SwitchCase) statement;
				if (switchCase.isDefault()) {
					jumpDefault = new Jump();
					push(jumpDefault);
					storeInstruction(); // jump
					statementsDefault = new ArrayList<>();
				} else {
					if (node.getAST().apiLevel() == AST.JLS13) {
						for (Object expression : switchCase.expressions()) {
							if (expression instanceof StringLiteral || expression instanceof TextBlock) {
								push(new SendMessage("equals", "(Ljava/lang/Object;)Z", 1, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
							} else {
								push(new EqualEqualOperator(Instruction.T_int, Instruction.T_int, true, fCounter));
							}
							push(new Dup());
							storeInstruction(); // dupe
							((Expression) expression).accept(this);
							storeInstruction(); // equal-equal
						}
					} else {
						if (switchCase.getExpression() instanceof StringLiteral || switchCase.getExpression() instanceof TextBlock) {
							push(new SendMessage("equals", "(Ljava/lang/Object;)Z", 1, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
						} else {
							push(new EqualEqualOperator(Instruction.T_int, Instruction.T_int, true, fCounter));
						}
						push(new Dup());
						storeInstruction(); // dupe
						switchCase.getExpression().accept(this);
						storeInstruction(); // equal-equal
					}
					ConditionalJump condJump = new ConditionalJump(true);
					push(condJump);
					storeInstruction(); // conditional jump
					if (currentslot.stmts != null) {
						currentslot = new slot();
						jumpsStatements.add(currentslot);
					}
					currentslot.jumps.add(condJump);
				}
			} else {
				if (statementsDefault != null) {
					statementsDefault.add(statement);
				} else {
					if (currentslot.stmts == null) {
						currentslot.stmts = new ArrayList<>();
					}
					currentslot.stmts.add(statement);
				}
			}
		}

		Jump jumpEnd = null;
		if (jumpDefault == null) {
			push(new Pop(0));
			storeInstruction(); // pop
			jumpEnd = new Jump();
			push(jumpEnd);
			storeInstruction(); // jump
		}

		for (slot slot : jumpsStatements) {
			for (ConditionalJump condJump : slot.jumps) {
				condJump.setOffset((fCounter - fInstructions.indexOf(condJump)) - 1);
			}
			if (currentslot.stmts != null) {
				push(new Pop(0));
				storeInstruction(); // pop
				for (Statement statement : currentslot.stmts) {
					statement.accept(this);
				}
			}
		}

		// default case
		if (jumpDefault != null) {
			jumpDefault.setOffset((fCounter - fInstructions.indexOf(jumpDefault)) - 1);
			push(new Pop(0));
			storeInstruction(); // pop
			for (Statement statement : statementsDefault) {
				statement.accept(this);
			}
		} else if(jumpEnd != null){
			jumpEnd.setOffset((fCounter - fInstructions.indexOf(jumpEnd)) - 1);
		}

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		String label = getLabel(node);
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > switchStart && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last instruction of the
					// switch
					jumpInstruction.setOffset((fCounter - instructionAddress) - 1);
				}
			}
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SynchronizedStatement)
	 */
	@Override
	public boolean visit(SynchronizedStatement node) {
		if (!isActive()) {
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement
	 * )
	 */
	@Override
	public boolean visit(TagElement node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * TextElement)
	 */
	@Override
	public boolean visit(TextElement node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ThisExpression)
	 */
	@Override
	public boolean visit(ThisExpression node) {
		if (!isActive()) {
			return false;
		}

		Name qualifier = node.getQualifier();
		int enclosingLevel = 0;
		if (qualifier != null) {
			ITypeBinding binding = (ITypeBinding) resolveBinding(qualifier);
			if (binding == null) {
				return false;
			}
			enclosingLevel = getEnclosingLevel(node, binding);
		}
		push(new PushThis(enclosingLevel));

		return false;
	}

	/**
	 * @see ASTVisitor#visit(ThrowStatement)
	 */
	@Override
	public boolean visit(ThrowStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new ThrowInstruction(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(TryStatement)
	 */
	@Override
	public boolean visit(TryStatement node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Try_statement_cannot_be_used_in_an_evaluation_expression_23);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(TypeDeclaration)
	 */
	@Override
	public boolean visit(TypeDeclaration node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Type_declaration_cannot_be_used_in_an_evaluation_expression_24);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(TypeDeclarationStatement)
	 */
	@Override
	public boolean visit(TypeDeclarationStatement node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Type_declaration_statement_cannot_be_used_in_an_evaluation_expression_25);
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * TypeParameter)
	 */
	@Override
	public boolean visit(TypeParameter node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(TypeLiteral)
	 */
	@Override
	public boolean visit(TypeLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushClassLiteralValue(fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(TypeMethodReference)
	 */
	@Override
	public boolean visit(TypeMethodReference node) {
		if (!isActive()) {
			return true;
		}

		try {
			RemoteEvaluatorBuilder builder = makeBuilder(node);
			builder.acceptMethodReference(node, node.resolveTypeBinding());
			RemoteEvaluator remoteEvaluator = builder.build();
			push(new RemoteOperator(builder.getSnippet(), node.getStartPosition(), remoteEvaluator));
			storeInstruction();
		} catch (JavaModelException | DebugException e) {
			addErrorMessage(e.getMessage());
			setHasError(true);
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(VariableDeclarationExpression)
	 */
	@Override
	public boolean visit(VariableDeclarationExpression node) {
		/*
		 * if it is in the code to execute, return <code>false</code>, we don't
		 * use the standard accept order. Otherwise, return true. We want to
		 * search the code to execute in variable declarations (in case of inner
		 * classes).
		 */
		if (!isActive()) {
			return true;
		}
		for (Iterator<VariableDeclarationFragment> iter = node.fragments().iterator(); iter.hasNext();) {
			iter.next().accept(this);
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(VariableDeclarationFragment)
	 */
	@Override
	public boolean visit(VariableDeclarationFragment node) {
		/*
		 * if it is in the code to execute, return <code>false</code>, we don't
		 * use the standard accept order. Otherwise, return true. We want to
		 * search the code to execute in variable declarations (in case of inner
		 * classes).
		 */
		if (!isActive()) {
			return true;
		}
		// get the type of the variable
		ITypeBinding varTypeBinding;
		ASTNode parent = node.getParent();
		switch (parent.getNodeType()) {
		case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
			varTypeBinding = resolveTypeBinding(((VariableDeclarationExpression) parent)
					.getType());
			break;
		case ASTNode.VARIABLE_DECLARATION_STATEMENT:
			varTypeBinding = resolveTypeBinding(((VariableDeclarationStatement) parent)
					.getType());
			break;
		default:
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Error_in_type_declaration_statement);
			return false;
		}
		if (varTypeBinding == null) {
			return false;
		}
		int typeDimension = varTypeBinding.getDimensions();
		ITypeBinding elementBinding = varTypeBinding;
		if (typeDimension != 0) {
			elementBinding = elementBinding.getElementType();
		}

		Expression initializer = node.getInitializer();
		push(new LocalVariableCreation(node.getName().getIdentifier(),
				getTypeSignature(elementBinding), typeDimension,
				elementBinding.isPrimitive(), initializer != null, fCounter));
		if (initializer != null) {
			initializer.accept(this);
			ITypeBinding expBindnig = initializer.resolveTypeBinding();
			if (expBindnig != null) {
				if (checkAutoBoxing(expBindnig, varTypeBinding)) {
					storeInstruction();
				}
			}
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(VariableDeclarationStatement)
	 */
	@Override
	public boolean visit(VariableDeclarationStatement node) {
		/*
		 * if it is in the code to execute, return <code>false</code>, we don't
		 * use the standard accept order. Otherwise, return true. We want to
		 * search the code to execute in variable declarations (in case of inner
		 * classes).
		 */
		if (!isActive()) {
			return true;
		}
		for (Iterator<VariableDeclarationFragment> iter = node.fragments().iterator(); iter.hasNext();) {
			iter.next().accept(this);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * WildcardType)
	 */
	@Override
	public boolean visit(WildcardType node) {
		// we shouldn't have to do anything
		return false;
	}

	/**
	 * @see ASTVisitor#visit(WhileStatement)
	 */
	@Override
	public boolean visit(WhileStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));
		return true;
	}

	// --------------------------

	private int getTypeId(Expression expression) {
		ITypeBinding typeBinding = expression.resolveTypeBinding();
		if (typeBinding == null) {
			return Instruction.T_undefined;
		}
		String typeName = typeBinding.getQualifiedName();
		if (typeBinding.isPrimitive()) {
			return getPrimitiveTypeId(typeName);
		} else if ("java.lang.String".equals(typeName)) { //$NON-NLS-1$
			return Instruction.T_String;
		} else {
			return Instruction.T_Object;
		}
	}

	private int getUnBoxedTypeId(Expression expression) {
		ITypeBinding typeBinding = expression.resolveTypeBinding();
		if (typeBinding == null) {
			return Instruction.T_undefined;
		}
		String typeName = typeBinding.getQualifiedName();
		if (typeBinding.isPrimitive()) {
			return getPrimitiveTypeId(typeName);
		} else if ("java.lang.String".equals(typeName)) { //$NON-NLS-1$
			return Instruction.T_String;
		} else {
			// un-boxing
			if ("java.lang.Integer".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_int;
			} else if ("java.lang.Character".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_char;
			} else if ("java.lang.Byte".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_byte;
			} else if ("java.lang.Short".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_short;
			} else if ("java.lang.Long".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_long;
			} else if ("java.lang.Float".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_float;
			} else if ("java.lang.Double".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_double;
			} else if ("java.lang.Boolean".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_boolean;
			}
			return Instruction.T_Object;
		}
	}

	private int getTypeId(Type type) {
		if (type.isPrimitiveType()) {
			return getPrimitiveTypeId(((PrimitiveType) type)
					.getPrimitiveTypeCode().toString());
		} else if (type.isSimpleType()) {
			SimpleType simpleType = (SimpleType) type;
			if ("java.lang.String".equals(simpleType.getName().getFullyQualifiedName())) { //$NON-NLS-1$
				return Instruction.T_String;
			}
			return Instruction.T_Object;
		} else if (type.isArrayType()) {
			return Instruction.T_Object;
		} else if (type.isParameterizedType()) {
			return Instruction.T_Object;
		} else {
			return Instruction.T_undefined;
		}

	}

	public static String removePrefixZerosAndUnderscores(String tokenString,
			boolean isLong) {
		char[] token = tokenString.toCharArray();
		int max = token.length;
		int start = 0;
		int end = max - 1;
		if (isLong) {
			end--; // remove the 'L' or 'l'
		}
		if (max > 1 && token[0] == '0') {
			if (max > 2 && (token[1] == 'x' || token[1] == 'X')) {
				start = 2;
			} else if (max > 2 && (token[1] == 'b' || token[1] == 'B')) {
				start = 2;
			} else {
				start = 1;
			}
		}
		boolean modified = false;
		boolean ignore = true;
		loop: for (int i = start; i < max; i++) {
			char currentChar = token[i];
			switch (currentChar) {
			case '0':
				// this is a prefix '0'
				if (ignore && !modified && (i < end)) {
					modified = true;
				}
				break;
			case '_':
				modified = true;
				break loop;
			default:
				ignore = false;
			}
		}
		if (!modified) {
			return tokenString;
		}
		ignore = true;
		StringBuilder buffer = new StringBuilder();
		buffer.append(token, 0, start);
		loop: for (int i = start; i < max; i++) {
			char currentChar = token[i];
			switch (currentChar) {
			case '0':
				if (ignore && (i < end)) {
					// this is a prefix '0'
					continue loop;
				}
				break;
			case '_':
				continue loop;
			default:
				ignore = false;
			}
			buffer.append(currentChar);
		}
		return buffer.toString();
	}

	/**
	 * Returns the method signature given the binding and the enclosing type
	 * signature (if there is one)
	 *
	 * @param methodBinding
	 *            the binding to get the signature for
	 * @param enclosingTypeSignature
	 *            the enclosing type signature or <code>null</code>
	 * @return the method signature for the given binding and enclosing type
	 *         signature
	 */
	private String getMethodSignature(IMethodBinding methodBinding,
			String enclosingTypeSignature) {
		methodBinding = methodBinding.getMethodDeclaration();
		ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
		int offset = 0;
		int argCount;
		String[] parameterSignatures;
		if (enclosingTypeSignature == null) {
			argCount = parameterTypes.length;
			parameterSignatures = new String[argCount];
		} else {
			offset = 1;
			argCount = parameterTypes.length + 1;
			parameterSignatures = new String[argCount];
			parameterSignatures[0] = enclosingTypeSignature;
		}
		for (int i = 0; i < parameterTypes.length; i++) {
			parameterSignatures[i + offset] = getTypeSignature(parameterTypes[i]);
		}
		String signature = Signature.createMethodSignature(parameterSignatures,
				getTypeSignature(methodBinding.getReturnType()));
		return signature;
	}

	public static int getPrimitiveTypeId(String typeName) {
		switch (typeName.charAt(0)) {
		case 'b': // byte or boolean
			switch (typeName.charAt(1)) {
			case 'o': // boolean;
				return Instruction.T_boolean;
			case 'y': // byte
				return Instruction.T_byte;
			}
			break;
		case 'c': // char
			return Instruction.T_char;
		case 'd': // double
			return Instruction.T_double;
		case 'f': // float
			return Instruction.T_float;
		case 'i': // int
			return Instruction.T_int;
		case 'l': // long
			return Instruction.T_long;
		case 'n':
			return Instruction.T_null;
		case 's': // short
			return Instruction.T_short;
		case 'v': // void
			return Instruction.T_void;
		}
		return Instruction.T_undefined;
	}

	/**
	 * Resolves and returns the type binding from the given expression reporting
	 * an error if the binding is <code>null</code>.
	 *
	 * @param expression
	 *            expression to resolve type binding for
	 * @return type binding or <code>null</code> if not available
	 */
	private ITypeBinding resolveTypeBinding(Expression expression) {
		ITypeBinding typeBinding = expression.resolveTypeBinding();
		if (typeBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_3,
					new Object[] { expression.toString() }));
		}
		return typeBinding;
	}

	/**
	 * Resolves and returns the type binding for the give type reporting an
	 * error if the binding is <code>null</code>.
	 *
	 * @param type
	 *            type to resolve binding for
	 * @return type binding or <code>null</code> if not available
	 */
	private ITypeBinding resolveTypeBinding(Type type) {
		ITypeBinding typeBinding = type.resolveBinding();
		if (typeBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_3,
					new Object[] { type.toString() }));
		}
		return typeBinding;
	}

	/**
	 * Resolves and returns the binding for the given name reporting an error if
	 * the binding is <code>null</code>.
	 *
	 * @param name
	 *            name to resolve binding for
	 * @return binding or <code>null</code> if not available
	 */
	private IBinding resolveBinding(Name name) {
		IBinding binding = name.resolveBinding();
		if (binding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_5,
					new Object[] { name.getFullyQualifiedName() }));
		}
		return binding;
	}

	/**
	 * Resolves and returns the type binding for the given name reporting an
	 * error if the binding is <code>null</code>.
	 *
	 * @param name
	 *            name to resolve type binding for
	 * @return type binding or <code>null</code> if not available
	 */
	private ITypeBinding resolveTypeBinding(Name name) {
		ITypeBinding typeBinding = name.resolveTypeBinding();
		if (typeBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_3,
					new Object[] { name.getFullyQualifiedName() }));
		}
		return typeBinding;
	}
}
