blob: 9a9011cefc7caff0603aa0290dc6c276eae68d44 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.instructions;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.jdt.debug.core.IJavaArrayType;
import org.eclipse.jdt.debug.core.IJavaClassObject;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaFieldVariable;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaReferenceType;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext;
import org.eclipse.jdt.internal.debug.eval.ast.engine.Interpreter;
import org.eclipse.osgi.util.NLS;
/**
* Common behavior for instructions.
*/
public abstract class Instruction {
private Interpreter fInterpreter;
public abstract int getSize();
public void setInterpreter(Interpreter interpreter) {
fInterpreter = interpreter;
}
public void setLastValue(IJavaValue value) {
fInterpreter.setLastValue(value);
}
public void stop() {
fInterpreter.stop();
}
public static int getBinaryPromotionType(int left, int right) {
return fTypeTable[left][right];
}
public abstract void execute() throws CoreException;
protected IRuntimeContext getContext() {
return fInterpreter.getContext();
}
protected IJavaDebugTarget getVM() {
return getContext().getVM();
}
/**
* Return the internal variable with the given name.
*
* @see Interpreter#getInternalVariable(String)
*/
protected IVariable getInternalVariable(String name) {
return fInterpreter.getInternalVariable(name);
}
/**
* Create and return a new internal variable with the given name and the
* given type.
*
* @see Interpreter#createInternalVariable(String, String)
*/
protected IVariable createInternalVariable(String name,
IJavaType referencType) {
return fInterpreter.createInternalVariable(name, referencType);
}
/**
* Answers the instance of Class that the given type represents.
*/
protected IJavaObject getClassObject(IJavaType type) throws CoreException {
if (type instanceof IJavaReferenceType) {
return ((IJavaReferenceType) type).getClassObject();
}
return null;
}
protected void jump(int offset) {
fInterpreter.jump(offset);
}
protected void push(Object object) {
fInterpreter.push(object);
}
protected Object pop() {
return fInterpreter.pop();
}
protected Object popValue() throws CoreException {
Object element = fInterpreter.pop();
if (element instanceof IJavaVariable) {
return ((IJavaVariable) element).getValue();
}
return element;
}
protected void pushNewValue(boolean value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(boolean value) {
return getVM().newValue(value);
}
protected void pushNewValue(byte value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(byte value) {
return getVM().newValue(value);
}
protected void pushNewValue(short value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(short value) {
return getVM().newValue(value);
}
protected void pushNewValue(int value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(int value) {
return getVM().newValue(value);
}
protected void pushNewValue(long value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(long value) {
return getVM().newValue(value);
}
protected void pushNewValue(char value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(char value) {
return getVM().newValue(value);
}
protected void pushNewValue(float value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(float value) {
return getVM().newValue(value);
}
protected void pushNewValue(double value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(double value) {
return getVM().newValue(value);
}
protected void pushNewValue(String value) {
fInterpreter.push(newValue(value));
}
protected IJavaValue newValue(String value) {
return getVM().newValue(value);
}
protected void pushNullValue() {
fInterpreter.push(nullValue());
}
protected IJavaValue nullValue() {
return getVM().nullValue();
}
public static int getUnaryPromotionType(int typeId) {
return fTypeTable[typeId][T_int];
}
protected IJavaType getType(String qualifiedName) throws CoreException {
// Force the class to be loaded, and record the class reference
// for later use if there are multiple classes with the same name.
IJavaClassObject classReference = getContext().classForName(
qualifiedName);
// Found many classes, look for the right one for this scope.
if (classReference == null) {
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK,
NLS.bind(
InstructionsEvaluationMessages.Instruction_No_type,
new String[] { qualifiedName }), null));
}
return classReference.getInstanceType();
}
/**
* Returns the primitive type with the given name.
*
* @param name
* type name, for example - "int"
* @return primitive type
* @throws CoreException
*/
protected IJavaType getPrimitiveType(String name) throws CoreException {
IJavaReferenceType type = null;
if ("boolean".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Boolean"); //$NON-NLS-1$
} else if ("byte".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Byte"); //$NON-NLS-1$
} else if ("char".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Character"); //$NON-NLS-1$
} else if ("double".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Double"); //$NON-NLS-1$
} else if ("float".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Float"); //$NON-NLS-1$
} else if ("int".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Integer"); //$NON-NLS-1$
} else if ("long".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Long"); //$NON-NLS-1$
} else if ("short".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Short"); //$NON-NLS-1$
} else if ("void".equals(name)) { //$NON-NLS-1$
type = (IJavaReferenceType) getType("java.lang.Void"); //$NON-NLS-1$
}
if (type != null) {
IJavaFieldVariable field = type.getField("TYPE"); //$NON-NLS-1$
IJavaClassObject clazz = (IJavaClassObject) field.getValue();
return clazz.getInstanceType();
}
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK,
NLS.bind(
InstructionsEvaluationMessages.Instruction_No_type,
new String[] { name }), null));
}
protected IJavaArrayType getArrayType(String typeSignature, int dimension)
throws CoreException {
String qualifiedName = RuntimeSignature.toString(typeSignature);
String braces = ""; //$NON-NLS-1$
for (int i = 0; i < dimension; i++) {
qualifiedName += "[]"; //$NON-NLS-1$
braces += "["; //$NON-NLS-1$
}
String signature = braces + typeSignature;
// Force the class to be loaded, and record the class reference
// for later use if there are multiple classes with the same name.
IJavaObject classReference = getContext().classForName(signature);
if (classReference == null) {
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK,
NLS.bind(
InstructionsEvaluationMessages.Instruction_No_type,
new String[] { qualifiedName }), null));
}
IJavaType[] types = getVM().getJavaTypes(qualifiedName);
checkTypes(types, qualifiedName);
if (types.length == 1) {
// Found only one class.
return (IJavaArrayType) types[0];
}
// Found many classes, look for the right one for this scope.
for (IJavaType type : types) {
if (classReference.equals(getClassObject(type))) {
return (IJavaArrayType) type;
}
}
// At this point a very strange thing has happened,
// the VM was able to return multiple types in the classesByName
// call, but none of them were the class that was returned in
// the classForName call.
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK,
NLS.bind(
InstructionsEvaluationMessages.Instruction_No_type,
new String[] { qualifiedName }), null));
}
protected void checkTypes(IJavaType[] types, String qualifiedName)
throws CoreException {
if (types == null || types.length == 0) {
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK,
NLS.bind(
InstructionsEvaluationMessages.Instruction_No_type,
new String[] { qualifiedName }), null));
}
}
static public final int T_undefined = 0;
static public final int T_Object = 1;
static public final int T_char = 2;
static public final int T_byte = 3;
static public final int T_short = 4;
static public final int T_boolean = 5;
static public final int T_void = 6;
static public final int T_long = 7;
static public final int T_double = 8;
static public final int T_float = 9;
static public final int T_int = 10;
static public final int T_String = 11;
static public final int T_null = 12;
private static final int[][] fTypeTable = {
/* undefined */{ T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined },
/* object */{ T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_String,
T_undefined },
/* char */{ T_undefined, T_undefined, T_int, T_int, T_int,
T_undefined, T_undefined, T_long, T_double, T_float, T_int,
T_String, T_undefined },
/* byte */{ T_undefined, T_undefined, T_int, T_int, T_int,
T_undefined, T_undefined, T_long, T_double, T_float, T_int,
T_String, T_undefined },
/* short */{ T_undefined, T_undefined, T_int, T_int, T_int,
T_undefined, T_undefined, T_long, T_double, T_float, T_int,
T_String, T_undefined },
/* boolean */{ T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_boolean, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_String,
T_undefined },
/* void */{ T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined },
/* long */{ T_undefined, T_undefined, T_long, T_long, T_long,
T_undefined, T_undefined, T_long, T_double, T_float,
T_long, T_String, T_undefined },
/* double */{ T_undefined, T_undefined, T_double, T_double,
T_double, T_undefined, T_undefined, T_double, T_double,
T_double, T_double, T_String, T_undefined },
/* float */{ T_undefined, T_undefined, T_float, T_float, T_float,
T_undefined, T_undefined, T_float, T_double, T_float,
T_float, T_String, T_undefined },
/* int */{ T_undefined, T_undefined, T_int, T_int, T_int,
T_undefined, T_undefined, T_long, T_double, T_float, T_int,
T_String, T_undefined },
/* String */{ T_undefined, T_String, T_String, T_String, T_String,
T_String, T_undefined, T_String, T_String, T_String,
T_String, T_String, T_String },
/* null */{ T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_undefined,
T_undefined, T_undefined, T_undefined, T_String,
T_undefined }, };
}