/**
* Copyright (c) 2014, the Railo Company Ltd.
* Copyright (c) 2015, Lucee Assosication Switzerland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lucee.transformer.bytecode.op;
import lucee.runtime.exp.TemplateException;
import lucee.transformer.Factory;
import lucee.transformer.TransformerException;
import lucee.transformer.bytecode.BytecodeContext;
import lucee.transformer.bytecode.expression.ExpressionBase;
import lucee.transformer.bytecode.util.Methods;
import lucee.transformer.bytecode.util.Methods_Operator;
import lucee.transformer.bytecode.util.Types;
import lucee.transformer.expression.ExprBoolean;
import lucee.transformer.expression.Expression;
import lucee.transformer.expression.literal.Literal;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
public final class OpBool extends ExpressionBase implements ExprBoolean {
private ExprBoolean left;
private ExprBoolean right;
private int operation;
/**
*
* @see lucee.transformer.bytecode.expression.ExpressionBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
*/
@Override
public Type _writeOut(BytecodeContext bc, int mode) throws TransformerException {
GeneratorAdapter adapter = bc.getAdapter();
if(mode==MODE_REF) {
_writeOut(bc,MODE_VALUE);
adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_BOOLEAN_FROM_BOOLEAN);
return Types.BOOLEAN;
}
Label doFalse = new Label();
Label end = new Label();
if(operation==Factory.OP_BOOL_AND) {
left.writeOut(bc, MODE_VALUE);
adapter.ifZCmp(Opcodes.IFEQ, doFalse);
right.writeOut(bc, MODE_VALUE);
adapter.ifZCmp(Opcodes.IFEQ, doFalse);
adapter.push(true);
adapter.visitJumpInsn(Opcodes.GOTO, end);
adapter.visitLabel(doFalse);
adapter.push(false);
adapter.visitLabel(end);
}
if(operation==Factory.OP_BOOL_OR) {
left.writeOut(bc, MODE_VALUE);
adapter.ifZCmp(Opcodes.IFNE, doFalse);
right.writeOut(bc, MODE_VALUE);
adapter.ifZCmp(Opcodes.IFNE, doFalse);
adapter.push(false);
adapter.visitJumpInsn(Opcodes.GOTO, end);
adapter.visitLabel(doFalse);
adapter.push(true);
adapter.visitLabel(end);
}
else if(operation==Factory.OP_BOOL_XOR) {
left.writeOut(bc, MODE_VALUE);
right.writeOut(bc, MODE_VALUE);
adapter.visitInsn(Opcodes.IXOR);
}
else if(operation==Factory.OP_BOOL_EQV) {
left.writeOut(bc,MODE_VALUE);
right.writeOut(bc,MODE_VALUE);
adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_EQV_BV_BV);
}
else if(operation==Factory.OP_BOOL_IMP) {
left.writeOut(bc,MODE_VALUE);
right.writeOut(bc,MODE_VALUE);
adapter.invokeStatic(Types.OPERATOR,Methods_Operator.OPERATOR_IMP_BV_BV);
}
return Types.BOOLEAN_VALUE;
}
private OpBool(Expression left, Expression right, int operation) {
super(left.getFactory(),left.getStart(),right.getEnd());
this.left=left.getFactory().toExprBoolean(left);
this.right=left.getFactory().toExprBoolean(right);
this.operation=operation;
}
/**
* Create a String expression from a Expression
* @param left
* @param right
*
* @return String expression
* @throws TemplateException
*/
public static ExprBoolean toExprBoolean(Expression left, Expression right,int operation) {
if(left instanceof Literal && right instanceof Literal) {
Boolean l=((Literal) left).getBoolean(null);
Boolean r=((Literal) right).getBoolean(null);
if(l!=null && r!=null) {
switch(operation) {
case Factory.OP_BOOL_AND: return left.getFactory().createLitBoolean(l.booleanValue()&&r.booleanValue(),left.getStart(),right.getEnd());
case Factory.OP_BOOL_OR: return left.getFactory().createLitBoolean(l.booleanValue()||r.booleanValue(),left.getStart(),right.getEnd());
case Factory.OP_BOOL_XOR: return left.getFactory().createLitBoolean(l.booleanValue()^r.booleanValue(),left.getStart(),right.getEnd());
}
}
}
return new OpBool(left,right,operation);
}
@Override
public String toString(){
return left+" "+toStringOperation()+" "+right;
}
private String toStringOperation() {
if(Factory.OP_BOOL_AND==operation) return "and";
if(Factory.OP_BOOL_OR==operation) return "or";
if(Factory.OP_BOOL_XOR==operation) return "xor";
if(Factory.OP_BOOL_EQV==operation) return "eqv";
if(Factory.OP_BOOL_IMP==operation) return "imp";
return operation+"";
}
}