/*******************************************************************************
 * Copyright (c) 2000, 2020 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.text.MessageFormat;
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;


/**
 * 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.
	 */
	static 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;
		}
		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;
		}

		String rewrittenLocalType = null;
		if (node.getAnonymousClassDeclaration() != null) {
			try {
				RemoteEvaluatorBuilder builder = makeBuilder(node);
				builder.acceptAnonymousClass(node, node.getType().resolveBinding());
				RemoteEvaluator remoteEvaluator = builder.build();
				push(new RemoteOperator(builder.getSnippet(), node.getStartPosition(), remoteEvaluator));

				push(new PushType(getTypeName(node.getType().resolveBinding())));
				storeInstruction();
				return false;

			} catch (JavaModelException | DebugException e) {
				addErrorMessage(e.getMessage());
				setHasError(true);
			}
		}

		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());

		boolean isLocalType = isALocalType(typeBinding);

		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 = null;
		if(isLocalType) {
			String methodSignature = getMethodSignature(methodBinding, null);
			signature = methodSignature.replace(methodBinding.getReturnType().getQualifiedName(), rewrittenLocalType).replace('.', '/');
		} else {
			signature = getMethodSignature(methodBinding,
					enclosingTypeSignature).replace('.', '/');
		}

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

		push(new PushType(isLocalType ? rewrittenLocalType : 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.parseInt(token.substring(1), 8);
		case 16:
			return Integer.parseInt(token.substring(2), 16);
		case 2:
			return Integer.parseInt(token.substring(2), 2);
		default:
			return Integer.parseInt(token, 10);
		}
	}

	/**
	 * 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.parseShort(token.substring(1), 8);
		case 16:
			return Short.parseShort(token.substring(2), 16);
		case 2:
			return Short.parseShort(token.substring(2), 2);
		default:
			return Short.parseShort(token, 10);
		}
	}

	/**
	 * 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.parseByte(token.substring(1), 8);
		case 16:
			return Byte.parseByte(token.substring(2), 16);
		case 2:
			return Byte.parseByte(token.substring(2), 2);
		default:
			return Byte.parseByte(token, 10);
		}
	}

	/**
	 * 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.parseLong(token.substring(1), 8);
		case 16:
			return Long.parseLong(token.substring(2), 16);
		case 2:
			return Long.parseLong(token.substring(2), 2);
		default:
			return Long.parseLong(token, 10);
		}
	}

	/**
	 * 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;
	}

	static 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.JLS14) {
						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;
	}
}
