/*
 * @(#)$Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 * @author Morten Jorgensen
 *
 */

package org.apache.xalan.xsltc.compiler;

import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
import org.apache.xalan.xsltc.compiler.util.MethodType;
import org.apache.xalan.xsltc.compiler.util.Type;
import org.apache.xalan.xsltc.compiler.util.TypeCheckError;

final class LogicalExpr extends Expression {

    public static final int OR  = 0;
    public static final int AND = 1;
	
    private final int  _op;     // operator
    private Expression _left;   // first operand
    private Expression _right;  // second operand

    private static final String[] Ops = { "or", "and" };

    /**
     * Creates a new logical expression - either OR or AND. Note that the
     * left- and right-hand side expressions can also be logical expressions,
     * thus creating logical trees representing structures such as
     * (a and (b or c) and d), etc...
     */
    public LogicalExpr(int op, Expression left, Expression right) {
	_op = op;
	(_left = left).setParent(this);
	(_right = right).setParent(this);
    }

    /**
     * Returns true if this expressions contains a call to position(). This is
     * needed for context changes in node steps containing multiple predicates.
     */
    public boolean hasPositionCall() {
	return (_left.hasPositionCall() || _right.hasPositionCall());
    }

    /**
     * Returns true if this expressions contains a call to last()
     */
    public boolean hasLastCall() {
            return (_left.hasLastCall() || _right.hasLastCall());
    }
    
    /**
     * Returns an object representing the compile-time evaluation 
     * of an expression. We are only using this for function-available
     * and element-available at this time.
     */
    public Object evaluateAtCompileTime() {
	final Object leftb = _left.evaluateAtCompileTime();
	final Object rightb = _right.evaluateAtCompileTime();

	// Return null if we can't evaluate at compile time
	if (leftb == null || rightb == null) {
	    return null;
	}

	if (_op == AND) {
	    return (leftb == Boolean.TRUE && rightb == Boolean.TRUE) ?
		Boolean.TRUE : Boolean.FALSE;
	}
	else {
	    return (leftb == Boolean.TRUE || rightb == Boolean.TRUE) ?
		Boolean.TRUE : Boolean.FALSE;
	}
    }

    /**
     * Returns this logical expression's operator - OR or AND represented
     * by 0 and 1 respectively.
     */
    public int getOp() {
	return(_op);
    }

    /**
     * Override the SyntaxTreeNode.setParser() method to make sure that the
     * parser is set for sub-expressions
     */
    public void setParser(Parser parser) {
	super.setParser(parser);
	_left.setParser(parser);
	_right.setParser(parser);
    }

    /**
     * Returns a string describing this expression
     */
    public String toString() {
	return Ops[_op] + '(' + _left + ", " + _right + ')';
    }

    /**
     * Type-check this expression, and possibly child expressions.
     */
    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
	// Get the left and right operand types
	Type tleft = _left.typeCheck(stable); 
	Type tright = _right.typeCheck(stable);

	// Check if the operator supports the two operand types
	MethodType wantType = new MethodType(Type.Void, tleft, tright);
	MethodType haveType = lookupPrimop(stable, Ops[_op], wantType);

	// Yes, the operation is supported
	if (haveType != null) {
	    // Check if left-hand side operand must be type casted
	    Type arg1 = (Type)haveType.argsType().elementAt(0);
	    if (!arg1.identicalTo(tleft))
		_left = new CastExpr(_left, arg1);
	    // Check if right-hand side operand must be type casted
	    Type arg2 = (Type) haveType.argsType().elementAt(1);
	    if (!arg2.identicalTo(tright))
		_right = new CastExpr(_right, arg1);
	    // Return the result type for the operator we will use
	    return _type = haveType.resultType();
	}
	throw new TypeCheckError(this);
    }

    /**
     * Compile the expression - leave boolean expression on stack
     */
    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
	translateDesynthesized(classGen, methodGen);
	synthesize(classGen, methodGen);
    }

    /**
     * Compile expression and update true/false-lists
     */
    public void translateDesynthesized(ClassGenerator classGen,
				       MethodGenerator methodGen) {

	final InstructionList il = methodGen.getInstructionList();
	final SyntaxTreeNode parent = getParent();

	// Compile AND-expression
	if (_op == AND) {

	    // Translate left hand side - must be true
	    _left.translateDesynthesized(classGen, methodGen);

	    // Need this for chaining any OR-expression children
	    InstructionHandle middle = il.append(NOP);

	    // Translate left right side - must be true
	    _right.translateDesynthesized(classGen, methodGen);

	    // Need this for chaining any OR-expression children
	    InstructionHandle after = il.append(NOP);

	    // Append child expression false-lists to our false-list
	    _falseList.append(_right._falseList.append(_left._falseList));

	    // Special case for OR-expression as a left child of AND.
	    // The true-list of OR must point to second clause of AND.
	    if ((_left instanceof LogicalExpr) &&
		(((LogicalExpr)_left).getOp() == OR)) {
		_left.backPatchTrueList(middle);
	    }
	    else if (_left instanceof NotCall) {
		_left.backPatchTrueList(middle);
	    }
	    else {
		_trueList.append(_left._trueList);
	    }

	    // Special case for OR-expression as a right child of AND
	    // The true-list of OR must point to true-list of AND.
	    if ((_right instanceof LogicalExpr) &&
		(((LogicalExpr)_right).getOp() == OR)) {
		_right.backPatchTrueList(after);
	    }
	    else if (_right instanceof NotCall) {
		_right.backPatchTrueList(after);
	    }
	    else {
		_trueList.append(_right._trueList);
	    }
	} 
	// Compile OR-expression
	else {
	    // Translate left-hand side expression and produce true/false list
	    _left.translateDesynthesized(classGen, methodGen);

	    // This GOTO is used to skip over the code for the last test
	    // in the case where the the first test succeeds
	    InstructionHandle ih = il.append(new GOTO(null));

	    // Translate right-hand side expression and produce true/false list
	    _right.translateDesynthesized(classGen, methodGen);

	    _left._trueList.backPatch(ih);
	    _left._falseList.backPatch(ih.getNext());
			
	    _falseList.append(_right._falseList);
	    _trueList.add(ih).append(_right._trueList);
	}
    }
}
