001    package railo.transformer.bytecode.op;
002    
003    import org.objectweb.asm.Label;
004    import org.objectweb.asm.Opcodes;
005    import org.objectweb.asm.Type;
006    import org.objectweb.asm.commons.GeneratorAdapter;
007    import org.objectweb.asm.commons.Method;
008    
009    import railo.transformer.bytecode.BytecodeContext;
010    import railo.transformer.bytecode.BytecodeException;
011    import railo.transformer.bytecode.expression.ExprBoolean;
012    import railo.transformer.bytecode.expression.Expression;
013    import railo.transformer.bytecode.expression.ExpressionBase;
014    import railo.transformer.bytecode.util.Methods;
015    import railo.transformer.bytecode.util.Methods_Operator;
016    import railo.transformer.bytecode.util.Types;
017    
018    public final class OPDecision extends ExpressionBase implements ExprBoolean {
019        
020        private Expression right;
021        private Expression left;
022        private int operation;
023    
024        public static final int LT=GeneratorAdapter.LT;
025        public static final int LTE=GeneratorAdapter.LE;
026        public static final int GTE=GeneratorAdapter.GE;
027        public static final int GT=GeneratorAdapter.GT;
028        public static final int EQ=GeneratorAdapter.EQ;
029        public static final int NEQ=GeneratorAdapter.NE; 
030        public static final int CT = 1000;
031        public static final int NCT = 1001;
032        public static final int EEQ = 1002;
033        public static final int NEEQ = 1003;
034        // int compare (Object, Object)
035        final public static Method METHOD_COMPARE = new Method("compare",
036                            Types.INT_VALUE,
037                            new Type[]{Types.OBJECT,Types.OBJECT});
038            
039        private OPDecision(Expression left, Expression right, int operation) {
040            super(left.getStart(),right.getEnd());
041            this.left=left;
042            this.right=right;  
043            this.operation=operation;
044        }
045        
046        /**
047         * Create a String expression from a operation
048         * @param left 
049         * @param right 
050         * 
051         * @return String expression
052         */
053        public static ExprBoolean toExprBoolean(Expression left, Expression right, int operation) {
054            return new OPDecision(left,right,operation);
055        }
056        
057        
058        public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
059            GeneratorAdapter adapter = bc.getAdapter();
060            if(mode==MODE_REF) {
061                _writeOut(bc,MODE_VALUE);
062                adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_BOOLEAN_FROM_BOOLEAN);
063                return Types.BOOLEAN;
064            }
065    
066            if(operation==CT)       {
067                left.writeOut(bc,MODE_REF);
068                right.writeOut(bc,MODE_REF);
069                    adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_CT);
070            }
071            else if(operation==NCT) {
072                left.writeOut(bc,MODE_REF);
073                right.writeOut(bc,MODE_REF);
074                    adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_NCT);
075            }
076            else if(operation==EEQ) {
077                left.writeOut(bc,MODE_REF);
078                right.writeOut(bc,MODE_REF);
079                    adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_EEQ);
080            }
081            else if(operation==NEEQ)        {
082                left.writeOut(bc,MODE_REF);
083                right.writeOut(bc,MODE_REF);
084                    adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_NEEQ);
085            }
086            else {
087                int iLeft = Types.getType(left.writeOut(bc,MODE_VALUE));
088                int iRight = Types.getType(right.writeOut(bc,MODE_VALUE));
089                
090                adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATORS[iLeft][iRight]);
091                
092                
093                    adapter.visitInsn(Opcodes.ICONST_0);
094                    
095                    Label l1 = new Label();
096                    Label l2 = new Label();
097                    adapter.ifCmp(Type.INT_TYPE,operation,l1);
098                    //adapter.visitJumpInsn(Opcodes.IF_ICMPEQ, l1);
099                    adapter.visitInsn(Opcodes.ICONST_0);
100                    adapter.visitJumpInsn(Opcodes.GOTO, l2);
101                    adapter.visitLabel(l1);
102                    adapter.visitInsn(Opcodes.ICONST_1);
103                    adapter.visitLabel(l2);
104            }
105            return Types.BOOLEAN_VALUE;
106        }
107    
108    }