|
|
|
|
@ -47,7 +47,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -47,7 +47,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
private static final SpelNodeImpl[] NO_CHILDREN = new SpelNodeImpl[0]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected int pos; // start = top 16bits, end = bottom 16bits
|
|
|
|
|
protected final int pos; // start = top 16bits, end = bottom 16bits
|
|
|
|
|
|
|
|
|
|
protected SpelNodeImpl[] children = SpelNodeImpl.NO_CHILDREN; |
|
|
|
|
|
|
|
|
|
@ -69,8 +69,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -69,8 +69,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
|
|
|
|
|
public SpelNodeImpl(int pos, SpelNodeImpl... operands) { |
|
|
|
|
this.pos = pos; |
|
|
|
|
// pos combines start and end so can never be zero because tokens cannot be zero length
|
|
|
|
|
Assert.isTrue(pos != 0, "Pos must not be 0"); |
|
|
|
|
if (!ObjectUtils.isEmpty(operands)) { |
|
|
|
|
this.children = operands; |
|
|
|
|
for (SpelNodeImpl operand : operands) { |
|
|
|
|
@ -84,7 +82,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -84,7 +82,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
/** |
|
|
|
|
* Return {@code true} if the next child is one of the specified classes. |
|
|
|
|
*/ |
|
|
|
|
protected boolean nextChildIs(Class<?>... clazzes) { |
|
|
|
|
protected boolean nextChildIs(Class<?>... classes) { |
|
|
|
|
if (this.parent != null) { |
|
|
|
|
SpelNodeImpl[] peers = this.parent.children; |
|
|
|
|
for (int i = 0, max = peers.length; i < max; i++) { |
|
|
|
|
@ -92,9 +90,9 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -92,9 +90,9 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
if (i + 1 >= max) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
Class<?> clazz = peers[i + 1].getClass(); |
|
|
|
|
for (Class<?> desiredClazz : clazzes) { |
|
|
|
|
if (clazz.equals(desiredClazz)) { |
|
|
|
|
Class<?> peerClass = peers[i + 1].getClass(); |
|
|
|
|
for (Class<?> desiredClass : classes) { |
|
|
|
|
if (peerClass == desiredClass) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -146,11 +144,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -146,11 +144,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
return (obj instanceof Class ? ((Class<?>) obj) : obj.getClass()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException { |
|
|
|
|
return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), getValueInternal(state), desiredReturnType); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public int getStartPosition() { |
|
|
|
|
return (this.pos >> 16); |
|
|
|
|
@ -161,10 +154,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -161,10 +154,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
return (this.pos & 0xffff); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException { |
|
|
|
|
throw new SpelEvaluationException(this.pos, SpelMessage.NOT_ASSIGNABLE, toStringAST()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Check whether a node can be compiled to bytecode. The reasoning in each node may |
|
|
|
|
* be different but will typically involve checking whether the exit type descriptor |
|
|
|
|
@ -177,9 +166,8 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -177,9 +166,8 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Generate the bytecode for this node into the supplied visitor. Context info about |
|
|
|
|
* the current expression being compiled is available in the codeflow object. For |
|
|
|
|
* example it will include information about the type of the object currently |
|
|
|
|
* on the stack. |
|
|
|
|
* the current expression being compiled is available in the codeflow object, e.g. |
|
|
|
|
* including information about the type of the object currently on the stack. |
|
|
|
|
* @param mv the ASM MethodVisitor into which code should be generated |
|
|
|
|
* @param cf a context object with info about what is on the stack |
|
|
|
|
*/ |
|
|
|
|
@ -192,6 +180,15 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
@@ -192,6 +180,15 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|
|
|
|
return this.exitTypeDescriptor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException { |
|
|
|
|
return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), getValueInternal(state), desiredReturnType); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException { |
|
|
|
|
throw new SpelEvaluationException(getStartPosition(), SpelMessage.NOT_ASSIGNABLE, toStringAST()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract TypedValue getValueInternal(ExpressionState expressionState) throws EvaluationException; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|