1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.expression.spel.ast;
18
19 import org.springframework.asm.Label;
20 import org.springframework.asm.MethodVisitor;
21 import org.springframework.expression.EvaluationException;
22 import org.springframework.expression.spel.CodeFlow;
23 import org.springframework.expression.spel.ExpressionState;
24 import org.springframework.expression.spel.support.BooleanTypedValue;
25
26
27
28
29
30
31
32 public class OpNE extends Operator {
33
34 public OpNE(int pos, SpelNodeImpl... operands) {
35 super("!=", pos, operands);
36 this.exitTypeDescriptor = "Z";
37 }
38
39 @Override
40 public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
41 Object left = getLeftOperand().getValueInternal(state).getValue();
42 Object right = getRightOperand().getValueInternal(state).getValue();
43 leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
44 rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
45 return BooleanTypedValue.forValue(!equalityCheck(state, left, right));
46 }
47
48
49
50 @Override
51 public boolean isCompilable() {
52 SpelNodeImpl left = getLeftOperand();
53 SpelNodeImpl right= getRightOperand();
54 if (!left.isCompilable() || !right.isCompilable()) {
55 return false;
56 }
57
58 String leftDesc = left.exitTypeDescriptor;
59 String rightDesc = right.exitTypeDescriptor;
60 DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, leftActualDescriptor, rightActualDescriptor);
61 return (!dc.areNumbers || dc.areCompatible);
62 }
63
64 @Override
65 public void generateCode(MethodVisitor mv, CodeFlow cf) {
66 String leftDesc = getLeftOperand().exitTypeDescriptor;
67 String rightDesc = getRightOperand().exitTypeDescriptor;
68 Label elseTarget = new Label();
69 Label endOfIf = new Label();
70 boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
71 boolean rightPrim = CodeFlow.isPrimitive(rightDesc);
72
73 DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, leftActualDescriptor, rightActualDescriptor);
74
75 if (dc.areNumbers && dc.areCompatible) {
76 char targetType = dc.compatibleType;
77
78 getLeftOperand().generateCode(mv, cf);
79 if (!leftPrim) {
80 CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
81 }
82
83 cf.enterCompilationScope();
84 getRightOperand().generateCode(mv, cf);
85 cf.exitCompilationScope();
86 if (!rightPrim) {
87 CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
88 }
89
90 if (targetType == 'D') {
91 mv.visitInsn(DCMPL);
92 mv.visitJumpInsn(IFEQ, elseTarget);
93 }
94 else if (targetType == 'F') {
95 mv.visitInsn(FCMPL);
96 mv.visitJumpInsn(IFEQ, elseTarget);
97 }
98 else if (targetType == 'J') {
99 mv.visitInsn(LCMP);
100 mv.visitJumpInsn(IFEQ, elseTarget);
101 }
102 else if (targetType == 'I' || targetType == 'Z') {
103 mv.visitJumpInsn(IF_ICMPEQ, elseTarget);
104 }
105 else {
106 throw new IllegalStateException("Unexpected descriptor "+leftDesc);
107 }
108 }
109 else {
110 getLeftOperand().generateCode(mv, cf);
111 getRightOperand().generateCode(mv, cf);
112 mv.visitJumpInsn(IF_ACMPEQ, elseTarget);
113 }
114 mv.visitInsn(ICONST_1);
115 mv.visitJumpInsn(GOTO,endOfIf);
116 mv.visitLabel(elseTarget);
117 mv.visitInsn(ICONST_0);
118 mv.visitLabel(endOfIf);
119 cf.pushDescriptor("Z");
120 }
121
122 }