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.getLine()); 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.getLine()); 129 case OR: return new LitBoolean(l.booleanValue()||r.booleanValue(),left.getLine()); 130 case XOR: return new LitBoolean(l.booleanValue()^r.booleanValue(),left.getLine()); 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