lucee.transformer.bytecode.op.OpBool.java Source code

Java tutorial

Introduction

Here is the source code for lucee.transformer.bytecode.op.OpBool.java

Source

/**
 *
 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
 *
 * 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.bytecode.BytecodeContext;
import lucee.transformer.bytecode.BytecodeException;
import lucee.transformer.bytecode.Literal;
import lucee.transformer.bytecode.cast.CastBoolean;
import lucee.transformer.bytecode.expression.ExprBoolean;
import lucee.transformer.bytecode.expression.Expression;
import lucee.transformer.bytecode.expression.ExpressionBase;
import lucee.transformer.bytecode.literal.LitBoolean;
import lucee.transformer.bytecode.util.Methods;
import lucee.transformer.bytecode.util.Methods_Operator;
import lucee.transformer.bytecode.util.Types;

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 {

    public static final int AND = 0;
    public static final int OR = 1;
    public static final int XOR = 2;
    public static final int EQV = 3;
    public static final int IMP = 4;

    private ExprBoolean left;
    private ExprBoolean right;
    private int operation;

    /**
     *
     * @see lucee.transformer.bytecode.expression.ExpressionBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
     */
    public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
        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 == 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 == 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 == XOR) {
            left.writeOut(bc, MODE_VALUE);
            right.writeOut(bc, MODE_VALUE);
            adapter.visitInsn(Opcodes.IXOR);
        } else if (operation == EQV) {

            left.writeOut(bc, MODE_VALUE);
            right.writeOut(bc, MODE_VALUE);
            adapter.invokeStatic(Types.OPERATOR, Methods_Operator.OPERATOR_EQV_BV_BV);
        } else if (operation == 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.getStart(), right.getEnd());
        this.left = CastBoolean.toExprBoolean(left);
        this.right = CastBoolean.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 AND:
                    return new LitBoolean(l.booleanValue() && r.booleanValue(), left.getStart(), right.getEnd());
                case OR:
                    return new LitBoolean(l.booleanValue() || r.booleanValue(), left.getStart(), right.getEnd());
                case XOR:
                    return new LitBoolean(l.booleanValue() ^ r.booleanValue(), left.getStart(), right.getEnd());
                }
            }
        }
        return new OpBool(left, right, operation);
    }

    public String toString() {
        return left + " " + toStringOperation() + " " + right;
    }

    private String toStringOperation() {
        if (AND == operation)
            return "and";
        if (OR == operation)
            return "or";
        if (XOR == operation)
            return "xor";
        if (EQV == operation)
            return "eqv";
        if (IMP == operation)
            return "imp";
        return operation + "";
    }
}