001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.op; 020 021import lucee.transformer.bytecode.BytecodeContext; 022import lucee.transformer.bytecode.BytecodeException; 023import lucee.transformer.bytecode.expression.ExprBoolean; 024import lucee.transformer.bytecode.expression.Expression; 025import lucee.transformer.bytecode.expression.ExpressionBase; 026import lucee.transformer.bytecode.util.Methods; 027import lucee.transformer.bytecode.util.Methods_Operator; 028import lucee.transformer.bytecode.util.Types; 029 030import org.objectweb.asm.Label; 031import org.objectweb.asm.Opcodes; 032import org.objectweb.asm.Type; 033import org.objectweb.asm.commons.GeneratorAdapter; 034import org.objectweb.asm.commons.Method; 035 036public final class OPDecision extends ExpressionBase implements ExprBoolean { 037 038 private Expression right; 039 private Expression left; 040 private int operation; 041 042 public static final int LT=GeneratorAdapter.LT; 043 public static final int LTE=GeneratorAdapter.LE; 044 public static final int GTE=GeneratorAdapter.GE; 045 public static final int GT=GeneratorAdapter.GT; 046 public static final int EQ=GeneratorAdapter.EQ; 047 public static final int NEQ=GeneratorAdapter.NE; 048 public static final int CT = 1000; 049 public static final int NCT = 1001; 050 public static final int EEQ = 1002; 051 public static final int NEEQ = 1003; 052 // int compare (Object, Object) 053 final public static Method METHOD_COMPARE = new Method("compare", 054 Types.INT_VALUE, 055 new Type[]{Types.OBJECT,Types.OBJECT}); 056 057 private OPDecision(Expression left, Expression right, int operation) { 058 super(left.getStart(),right.getEnd()); 059 this.left=left; 060 this.right=right; 061 this.operation=operation; 062 } 063 064 /** 065 * Create a String expression from a operation 066 * @param left 067 * @param right 068 * 069 * @return String expression 070 */ 071 public static ExprBoolean toExprBoolean(Expression left, Expression right, int operation) { 072 return new OPDecision(left,right,operation); 073 } 074 075 076 public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { 077 GeneratorAdapter adapter = bc.getAdapter(); 078 if(mode==MODE_REF) { 079 _writeOut(bc,MODE_VALUE); 080 adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_BOOLEAN_FROM_BOOLEAN); 081 return Types.BOOLEAN; 082 } 083 084 if(operation==CT) { 085 left.writeOut(bc,MODE_REF); 086 right.writeOut(bc,MODE_REF); 087 adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_CT); 088 } 089 else if(operation==NCT) { 090 left.writeOut(bc,MODE_REF); 091 right.writeOut(bc,MODE_REF); 092 adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_NCT); 093 } 094 else if(operation==EEQ) { 095 left.writeOut(bc,MODE_REF); 096 right.writeOut(bc,MODE_REF); 097 adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_EEQ); 098 } 099 else if(operation==NEEQ) { 100 left.writeOut(bc,MODE_REF); 101 right.writeOut(bc,MODE_REF); 102 adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_NEEQ); 103 } 104 else { 105 int iLeft = Types.getType(left.writeOut(bc,MODE_VALUE)); 106 int iRight = Types.getType(right.writeOut(bc,MODE_VALUE)); 107 108 adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATORS[iLeft][iRight]); 109 110 111 adapter.visitInsn(Opcodes.ICONST_0); 112 113 Label l1 = new Label(); 114 Label l2 = new Label(); 115 adapter.ifCmp(Type.INT_TYPE,operation,l1); 116 //adapter.visitJumpInsn(Opcodes.IF_ICMPEQ, l1); 117 adapter.visitInsn(Opcodes.ICONST_0); 118 adapter.visitJumpInsn(Opcodes.GOTO, l2); 119 adapter.visitLabel(l1); 120 adapter.visitInsn(Opcodes.ICONST_1); 121 adapter.visitLabel(l2); 122 } 123 return Types.BOOLEAN_VALUE; 124 } 125 126}