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    
008    import railo.runtime.exp.TemplateException;
009    import railo.transformer.bytecode.BytecodeContext;
010    import railo.transformer.bytecode.BytecodeException;
011    import railo.transformer.bytecode.Literal;
012    import railo.transformer.bytecode.cast.CastBoolean;
013    import railo.transformer.bytecode.expression.ExprBoolean;
014    import railo.transformer.bytecode.expression.Expression;
015    import railo.transformer.bytecode.expression.ExpressionBase;
016    import railo.transformer.bytecode.literal.LitBoolean;
017    import railo.transformer.bytecode.util.Methods;
018    import railo.transformer.bytecode.util.Methods_Operator;
019    import railo.transformer.bytecode.util.Types;
020    
021    public final class OpBool extends ExpressionBase implements ExprBoolean {
022    
023        public static final int AND=0;
024        public static final int OR=1;
025        public static final int XOR=2;
026            public static final int EQV = 3;
027            public static final int IMP = 4;
028        
029        private ExprBoolean left;
030        private ExprBoolean right;
031        private int operation;
032    
033        /**
034         *
035         * @see railo.transformer.bytecode.expression.ExpressionBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
036         */
037        public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
038            GeneratorAdapter adapter = bc.getAdapter();
039            
040            if(mode==MODE_REF) {
041                _writeOut(bc,MODE_VALUE);
042                adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_BOOLEAN_FROM_BOOLEAN);
043                return Types.BOOLEAN;
044            }
045            
046            
047            Label doFalse = new Label();
048            Label end = new Label();
049    
050            if(operation==AND) {
051                    left.writeOut(bc, MODE_VALUE);
052                    adapter.ifZCmp(Opcodes.IFEQ, doFalse);
053                    
054                    right.writeOut(bc, MODE_VALUE);
055                    adapter.ifZCmp(Opcodes.IFEQ, doFalse);
056                    adapter.push(true);
057                    
058                    adapter.visitJumpInsn(Opcodes.GOTO, end);
059                    adapter.visitLabel(doFalse);
060    
061                    adapter.push(false);
062                    adapter.visitLabel(end);
063            }
064            if(operation==OR) {
065                    left.writeOut(bc, MODE_VALUE);
066                    adapter.ifZCmp(Opcodes.IFNE, doFalse);
067    
068                    right.writeOut(bc, MODE_VALUE);
069                    adapter.ifZCmp(Opcodes.IFNE, doFalse);
070    
071                    adapter.push(false);
072                    adapter.visitJumpInsn(Opcodes.GOTO, end);
073                    adapter.visitLabel(doFalse);
074    
075                    adapter.push(true);
076                    adapter.visitLabel(end);
077            }
078            else if(operation==XOR) {
079                    left.writeOut(bc, MODE_VALUE);
080                    right.writeOut(bc, MODE_VALUE);
081                    adapter.visitInsn(Opcodes.IXOR);
082            }
083            else if(operation==EQV) {
084    
085                left.writeOut(bc,MODE_VALUE);
086                right.writeOut(bc,MODE_VALUE);
087                adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_EQV_BV_BV);
088            }
089            else if(operation==IMP) {
090    
091                left.writeOut(bc,MODE_VALUE);
092                right.writeOut(bc,MODE_VALUE);
093                adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_IMP_BV_BV);
094            }
095            return Types.BOOLEAN_VALUE;
096            
097        }
098        
099    
100        
101        
102        
103        
104        
105        private OpBool(Expression left, Expression right, int operation) {
106            super(left.getStart(),right.getEnd());
107            this.left=CastBoolean.toExprBoolean(left);
108            this.right=CastBoolean.toExprBoolean(right);  
109            this.operation=operation;
110        }
111        
112        /**
113         * Create a String expression from a Expression
114         * @param left 
115         * @param right 
116         * 
117         * @return String expression
118         * @throws TemplateException 
119         */
120        public static ExprBoolean toExprBoolean(Expression left, Expression right,int operation) {
121            if(left instanceof Literal && right instanceof Literal) {
122                    Boolean l=((Literal) left).getBoolean(null);
123                    Boolean r=((Literal) right).getBoolean(null);
124                    
125                    
126                    if(l!=null && r!=null) {
127                            switch(operation) {
128                            case AND:       return new LitBoolean(l.booleanValue()&&r.booleanValue(),left.getStart(),right.getEnd());
129                            case OR:        return new LitBoolean(l.booleanValue()||r.booleanValue(),left.getStart(),right.getEnd());
130                            case XOR:       return new LitBoolean(l.booleanValue()^r.booleanValue(),left.getStart(),right.getEnd());
131                            }
132                    }
133            }
134            return new OpBool(left,right,operation);
135        }
136        
137        public String toString(){
138            return left+" "+toStringOperation()+" "+right;
139        }
140    
141            private String toStringOperation() {
142                    if(AND==operation)      return "and";
143                    if(OR==operation)       return "or";
144                    if(XOR==operation)      return "xor";
145                    if(EQV==operation)      return "eqv";
146                    if(IMP==operation)      return "imp";
147                    return operation+"";
148            }
149    }
150