package org.eclipse.jdt.internal.eval; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import org.eclipse.jdt.internal.compiler.codegen.*; | |
import org.eclipse.jdt.internal.compiler.ast.Assignment; | |
import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; | |
import org.eclipse.jdt.internal.compiler.ast.Expression; | |
import org.eclipse.jdt.internal.compiler.ast.IntLiteral; | |
import org.eclipse.jdt.internal.compiler.lookup.*; | |
public class CodeSnippetCodeStream extends CodeStream { | |
static InvocationSite NO_INVOCATION_SITE = | |
new InvocationSite(){ | |
public boolean isSuperAccess(){ return false; } | |
public boolean isTypeAccess() { return false; } | |
public void setDepth(int depth) {} | |
public void setFieldIndex(int depth){} | |
}; | |
/** | |
* CodeSnippetCodeStream constructor comment. | |
* @param classFile org.eclipse.jdt.internal.compiler.ClassFile | |
*/ | |
public CodeSnippetCodeStream(org.eclipse.jdt.internal.compiler.ClassFile classFile) { | |
super(classFile); | |
} | |
protected void checkcast(int baseId) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_checkcast; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_checkcast); | |
} | |
switch (baseId) { | |
case T_byte : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangByte()); | |
break; | |
case T_short : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangShort()); | |
break; | |
case T_char : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter()); | |
break; | |
case T_int : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangInteger()); | |
break; | |
case T_long : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangLong()); | |
break; | |
case T_float : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangFloat()); | |
break; | |
case T_double : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangDouble()); | |
break; | |
case T_boolean : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean()); | |
} | |
} | |
public void generateEmulatedAccessForMethod(Scope scope, MethodBinding methodBinding) { | |
CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this; | |
localCodeStream.generateEmulationForMethod(scope, methodBinding); | |
localCodeStream.invokeJavaLangReflectMethodInvoke(); | |
} | |
public void generateEmulatedReadAccessForField(FieldBinding fieldBinding) { | |
CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this; | |
localCodeStream.generateEmulationForField(fieldBinding); | |
// swap the field with the receiver | |
this.swap(); | |
localCodeStream.invokeJavaLangReflectFieldGetter(fieldBinding.type.id); | |
if (!fieldBinding.type.isBaseType()) { | |
this.checkcast(fieldBinding.type); | |
} | |
} | |
public void generateEmulatedWriteAccessForField(FieldBinding fieldBinding) { | |
CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this; | |
localCodeStream.invokeJavaLangReflectFieldSetter(fieldBinding.type.id); | |
} | |
public void generateEmulationForConstructor(Scope scope, MethodBinding methodBinding) { | |
// leave a java.lang.reflect.Field object on the stack | |
CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this; | |
this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
int paramLength = methodBinding.parameters.length; | |
this.generateInlinedValue(paramLength); | |
this.newArray(scope, new ArrayBinding(scope.getType(TypeBinding.JAVA_LANG_CLASS), 1)); | |
if (paramLength > 0) { | |
this.dup(); | |
for (int i = 0; i < paramLength; i++) { | |
this.generateInlinedValue(i); | |
TypeBinding parameter = methodBinding.parameters[i]; | |
if (parameter.isBaseType()) { | |
this.getTYPE(parameter.id); | |
} else if (parameter.isArrayType()) { | |
ArrayBinding array = (ArrayBinding)parameter; | |
if (array.leafComponentType.isBaseType()) { | |
this.getTYPE(array.leafComponentType.id); | |
} else { | |
this.ldc(String.valueOf(array.leafComponentType.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
} | |
int dimensions = array.dimensions; | |
this.generateInlinedValue(dimensions); | |
this.newarray(T_int); | |
this.invokeArrayNewInstance(); | |
this.invokeObjectGetClass(); | |
} else { | |
// parameter is a reference binding | |
this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
} | |
this.aastore(); | |
if (i < paramLength - 1) { | |
this.dup(); | |
} | |
} | |
} | |
localCodeStream.invokeClassGetDeclaredConstructor(); | |
this.dup(); | |
this.iconst_1(); | |
localCodeStream.invokeAccessibleObjectSetAccessible(); | |
} | |
public void generateEmulationForField(FieldBinding fieldBinding) { | |
// leave a java.lang.reflect.Field object on the stack | |
CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this; | |
this.ldc(String.valueOf(fieldBinding.declaringClass.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
this.ldc(String.valueOf(fieldBinding.name)); | |
localCodeStream.invokeClassGetDeclaredField(); | |
this.dup(); | |
this.iconst_1(); | |
localCodeStream.invokeAccessibleObjectSetAccessible(); | |
} | |
public void generateEmulationForMethod(Scope scope, MethodBinding methodBinding) { | |
// leave a java.lang.reflect.Field object on the stack | |
CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this; | |
this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
this.ldc(String.valueOf(methodBinding.selector)); | |
int paramLength = methodBinding.parameters.length; | |
this.generateInlinedValue(paramLength); | |
this.newArray(scope, new ArrayBinding(scope.getType(TypeBinding.JAVA_LANG_CLASS), 1)); | |
if (paramLength > 0) { | |
this.dup(); | |
for (int i = 0; i < paramLength; i++) { | |
this.generateInlinedValue(i); | |
TypeBinding parameter = methodBinding.parameters[i]; | |
if (parameter.isBaseType()) { | |
this.getTYPE(parameter.id); | |
} else if (parameter.isArrayType()) { | |
ArrayBinding array = (ArrayBinding)parameter; | |
if (array.leafComponentType.isBaseType()) { | |
this.getTYPE(array.leafComponentType.id); | |
} else { | |
this.ldc(String.valueOf(array.leafComponentType.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
} | |
int dimensions = array.dimensions; | |
this.generateInlinedValue(dimensions); | |
this.newarray(T_int); | |
this.invokeArrayNewInstance(); | |
this.invokeObjectGetClass(); | |
} else { | |
// parameter is a reference binding | |
this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); | |
this.invokeClassForName(); | |
} | |
this.aastore(); | |
if (i < paramLength - 1) { | |
this.dup(); | |
} | |
} | |
} | |
localCodeStream.invokeClassGetDeclaredMethod(); | |
this.dup(); | |
this.iconst_1(); | |
localCodeStream.invokeAccessibleObjectSetAccessible(); | |
} | |
public void generateObjectWrapperForType(TypeBinding valueType) { | |
/* The top of stack must be encapsulated inside | |
* a wrapper object if it corresponds to a base type | |
*/ | |
char[][] wrapperTypeCompoundName = null; | |
switch (valueType.id) { | |
case T_int : // new: java.lang.Integer | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Integer".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_boolean : // new: java.lang.Boolean | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Boolean".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_byte : // new: java.lang.Byte | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Byte".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_char : // new: java.lang.Character | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Character".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_float : // new: java.lang.Float | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Float".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_double : // new: java.lang.Double | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Double".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_short : // new: java.lang.Short | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Short".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
case T_long : // new: java.lang.Long | |
wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Long".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ | |
break; | |
} | |
TypeBinding wrapperType = methodDeclaration.scope.getType(wrapperTypeCompoundName); | |
new_(wrapperType); | |
if (valueType.id == T_long || valueType.id == T_double) { | |
dup_x2(); | |
dup_x2(); | |
pop(); | |
} else { | |
dup_x1(); | |
swap(); | |
} | |
MethodBinding methodBinding = methodDeclaration.scope.getMethod( | |
wrapperType, | |
QualifiedNamesConstants.Init, | |
new TypeBinding[] {valueType}, | |
NO_INVOCATION_SITE); | |
invokespecial(methodBinding); | |
} | |
public void getBaseTypeValue(int baseTypeID) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
switch (baseTypeID) { | |
case T_byte : | |
// invokevirtual: byteValue() | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangByteByteValue()); | |
break; | |
case T_short : | |
// invokevirtual: shortValue() | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangShortShortValue()); | |
break; | |
case T_char : | |
// invokevirtual: charValue() | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangCharacterCharValue()); | |
break; | |
case T_int : | |
// invokevirtual: intValue() | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangIntegerIntValue()); | |
break; | |
case T_long : | |
// invokevirtual: longValue() | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangLongLongValue()); | |
break; | |
case T_float : | |
// invokevirtual: floatValue() | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangFloatFloatValue()); | |
break; | |
case T_double : | |
// invokevirtual: doubleValue() | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangDoubleDoubleValue()); | |
break; | |
case T_boolean : | |
// invokevirtual: booleanValue() | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangBooleanBooleanValue()); | |
} | |
} | |
protected void invokeAccessibleObjectSetAccessible() { | |
// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectAccessibleObjectSetAccessible()); | |
stackDepth-=2; | |
} | |
protected void invokeArrayNewInstance() { | |
// invokestatic: java.lang.reflect.Array.newInstance(Ljava.lang.Class;int[])Ljava.lang.reflect.Array; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokestatic); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectArrayNewInstance()); | |
stackDepth--; | |
} | |
protected void invokeClassGetDeclaredConstructor() { | |
// invokevirtual: java.lang.Class getDeclaredConstructor([Ljava.lang.Class)Ljava.lang.reflect.Constructor; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangClassGetDeclaredConstructor()); | |
stackDepth--; | |
} | |
protected void invokeClassGetDeclaredField() { | |
// invokevirtual: java.lang.Class.getDeclaredField(Ljava.lang.String)Ljava.lang.reflect.Field; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangClassGetDeclaredField()); | |
stackDepth--; | |
} | |
protected void invokeClassGetDeclaredMethod() { | |
// invokevirtual: java.lang.Class getDeclaredMethod(Ljava.lang.String, [Ljava.lang.Class)Ljava.lang.reflect.Method; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangClassGetDeclaredMethod()); | |
stackDepth-=2; | |
} | |
protected void invokeJavaLangReflectConstructorNewInstance() { | |
// invokevirtual: java.lang.reflect.Constructor.newInstance([Ljava.lang.Object;)Ljava.lang.Object; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectConstructorNewInstance()); | |
stackDepth--; | |
} | |
protected void invokeJavaLangReflectFieldGetter(int typeID) { | |
countLabels = 0; | |
int usedTypeID; | |
if (typeID == T_null) | |
usedTypeID = T_Object; | |
else | |
usedTypeID = typeID; | |
// invokevirtual | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexJavaLangReflectFieldGetter(typeID)); | |
if ((usedTypeID != T_long) && (usedTypeID != T_double)) { | |
stackDepth--; | |
} | |
} | |
protected void invokeJavaLangReflectFieldSetter(int typeID) { | |
countLabels = 0; | |
int usedTypeID; | |
if (typeID == T_null) | |
usedTypeID = T_Object; | |
else | |
usedTypeID = typeID; | |
// invokevirtual | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexJavaLangReflectFieldSetter(typeID)); | |
if ((usedTypeID != T_long) && (usedTypeID != T_double)) { | |
stackDepth-=3; | |
} else { | |
stackDepth-=4; | |
} | |
} | |
protected void invokeJavaLangReflectMethodInvoke() { | |
// invokevirtual: java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectMethodInvoke()); | |
stackDepth-=2; | |
} | |
protected void invokeObjectGetClass() { | |
// invokevirtual: java.lang.Object.getClass()Ljava.lang.Class; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangObjectGetClass()); | |
} | |
} |