Package org.openquark.cal.internal.machine

Source Code of org.openquark.cal.internal.machine.BasicOpTuple

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * 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.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS 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 COPYRIGHT OWNER OR 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.
*/


/*
* BasicOpTuple.java
* Creation date: (May 1, 2002)
* By: Bo Ilic
*/
package org.openquark.cal.internal.machine;

import org.openquark.cal.compiler.Expression;
import org.openquark.cal.compiler.ForeignFunctionInfo;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.UnableToResolveForeignEntityException;
import org.openquark.cal.internal.machine.primitiveops.PrimOps;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.runtime.ErrorInfo;


/**
* Expression tuple for basic operations.
* This class is used to recognize fully-saturated calls to built-in or
* foreign functions within an expression.
*/
public final class BasicOpTuple {
   
    /** The type of primitive op being invoked (InstructionBase.PRIMOP_* manifest). */
    private final int primOp;
   
    /** The foreign function info if the basic op is in fact an external function call. Null otherwise. */
    private final ForeignFunctionInfo foreignFunctionInfo;
   
    /** The information use to identify the source of an error when an exception is thrown. Only for PrimopERROR.
     * This may be null for the case of internally generated expressions. */
    private final ErrorInfo errorInfo;
   
    /** The argument expressions. */
    private final Expression[] argumentExpressions;
   
    /** The name of the operation. */
    private final QualifiedName opName;
   
    //public static final BasicOpTuple emptyBasicOpTuple = new BasicOpTuple(PrimOps.PRIMOP_NOP, null, null);
   
   
    private BasicOpTuple(int primOp, ForeignFunctionInfo foreignFunctionInfo, ErrorInfo errorInfo, Expression [] argumentExpressions, QualifiedName opName) {
        this.primOp = primOp;
        this.foreignFunctionInfo = foreignFunctionInfo;
        this.errorInfo = errorInfo;
        this.argumentExpressions = argumentExpressions;
        this.opName = opName;
    }
   
    /**
     * @return primitive operator index of the basic op.
     * Creation date: (May 1, 2002)
     */       
    public int getPrimitiveOp () {
           
        return primOp;
    }
     
    /**
     * @return the foreign function info if the basic op is in fact an external function call.
     * Creation date: (May 3, 2002)
     */        
    public ForeignFunctionInfo getForeignFunctionInfo () {
        return foreignFunctionInfo;
    }         
   
    /**
     * @return The error info if the basic op is in fact an error call.
     */
    public ErrorInfo getErrorInfo() {
        return errorInfo;
    }
   
    /**
     * @return the number of expression arguments in the basic op.
     * Creation date: (May 1, 2002)
     */       
    public int getNArguments () {
       
        if (argumentExpressions == null) {
            return -1;
        }
           
        return argumentExpressions.length;
    }
   
    /**
     * Accessor for the argument expressions in the basic op.
     * @param argN zero-based expression argument index.
     * @return Expression the expression argument
     * Creation date: (May 1, 2002)
     */   
    public Expression getArgument (int argN) {
       
        return argumentExpressions [argN];     
   
   
    /**
     * @return the qualified name of the operation
     */
    public QualifiedName getName () {
        return opName;
    }
   
    /**
     * Determine if the expression is a basic operation.
     * If the expression matches a basic operation,
     * a BasicOpTuple will be populated with operator parameters and returned. 
     * Otherwise, null is returned.
     * If the expression corresponds to a foreign function invocation, and the field/method/constructor could not be resolved,
     * a CodeGenerationException is thrown.
     * Creation date: (3/24/00 3:53:34 PM)
     * @param e Expression the expression to test
     * @return BasicOpTuple instantiated if the expression matched as a basic operation, null otherwise
     * @throws CodeGenerationException if the expression corresponds to a foreign function invocation, and the field/method/constructor could not be resolved.
     */
    public static BasicOpTuple isBasicOp(Expression e) throws CodeGenerationException {
       
        // Look for all the elements of a basic operation
        // Has to match: EAp(EAp(EVar <op>) e1) e2, for a binary op
        // Has to match: EAp(EVar <op>) e1, for a unary op
        // Where e<n> are the argument expressions

        Expression[] appChain = appChain (e);
        if (appChain == null) {
            return null;
        }

        int nArguments = appChain.length - 1;
        Expression.Var var = appChain[0].asVar();
          
        // Check that the full number of arguments are supplied.
        ForeignFunctionInfo foreignFunctionInfo = var.getForeignFunctionInfo();
        PrimOps.PrimOpInfo info = null;
        info = PrimOps.fetchInfo (var.getName());
        int nExpectedArguments;
       
        if (info == null && foreignFunctionInfo == null) {
            //not a built-in primitive or a foreign function call
            return null;
        }
       
       
        if (info != null) { 
            nExpectedArguments = info.getArity ();
        } else
        if (foreignFunctionInfo != null) {
            try {
                nExpectedArguments = foreignFunctionInfo.getNArguments();
            } catch (UnableToResolveForeignEntityException ex) {
                throw new CodeGenerationException("Failed to resolve foreign method, field, or constructor.", ex);
            }
        } else {
            //not a built-in primitive or a foreign function call
            return null;
        }
                     
        if (nExpectedArguments != nArguments) {
            return null;
        }
           
        Expression[] argumentExpressions = new Expression [nArguments];
        for (int i = 0; i < nArguments; ++i) {
            argumentExpressions[i] = appChain[i+1];
        }
       
        ErrorInfo errorInfo = null;
        if (var.getErrorInfo() != null){
            Expression.ErrorInfo ei = var.getErrorInfo();
            errorInfo = new ErrorInfo(ei.getTopLevelFunctionName(), ei.getLine(), ei.getColumn());
        }
        return new BasicOpTuple (info == null ? PrimOps.PRIMOP_FOREIGN_FUNCTION : info.getCode(), foreignFunctionInfo, errorInfo, argumentExpressions, var.getName());                    
    }   
   
    /**
     * Determine if the expression is an application of 'and' or 'or'.
     * If the expression matches either operation
     * a BasicOpTuple will be populated with operator parameters and returned. 
     * Otherwise, null is returned.
     * @param e Expression the expression to test
     * @return BasicOpTuple instantiated if the expression matched as a basic operation, null otherwise
     */
    public static BasicOpTuple isAndOr(Expression e) {
       
        // Has to match: EAp(EAp(EVar <op>) e1) e2, where <op> is 'and' or 'or'.

        Expression[] appChain = appChain (e);
        if (appChain == null) {
            return null;
        }

        int nArguments = appChain.length - 1;
        Expression.Var var = appChain[0].asVar();
          
        // fixup the names for Prelude.and and Prelude.or
        QualifiedName qn = var.getName();
        if (!qn.getModuleName().equals(CAL_Prelude.MODULE_NAME) || (!qn.getUnqualifiedName().equals("and") && !qn.getUnqualifiedName().equals("or"))) {
            return null;
        }
       
        int opCode;
        if (qn.getUnqualifiedName().equals("and")) {
            opCode = PrimOps.PRIMOP_AND;
        } else {
            opCode = PrimOps.PRIMOP_OR;
        }
           
       
        if (nArguments != 2) {
            return null;
        }
           
        Expression[] argumentExpressions = new Expression [nArguments];
        for (int i = 0; i < nArguments; ++i) {
            argumentExpressions[i] = appChain[i+1];
        }
       
        return new BasicOpTuple (opCode, null, null, argumentExpressions, qn);                    
    }                 
   
    /**
     * Convert an application chain to an array.
     * @param root
     * @return null if this is not an SC application, array of Expression otherwise.
     */
    static private Expression[] appChain (Expression root) {
        if (root.asAppl() != null) {
            // Walk down the left branch.
            Expression c = root;
            int nArgs = 0;
            while (c instanceof Expression.Appl) {
                nArgs++;
                c = ((Expression.Appl)c).getE1();
            }
           
            // At this point c should be an Expression.Var
            if (!(c instanceof Expression.Var)) {
                return null;
            }
           
            Expression[] chain = new Expression [nArgs + 1];
            chain[0] = c;
            c = root;
            for (int i = nArgs; i >= 1; i--) {
                chain[i] = ((Expression.Appl)c).getE2();
                c = ((Expression.Appl)c).getE1();
            }
   
            return chain;
        } else
        if (root.asTailRecursiveCall() != null) {
            return appChain (root.asTailRecursiveCall().getApplForm());
        } else
        if (root.asVar() != null) {
            return new Expression[]{root};
        }
           
        return null;
    }
}
TOP

Related Classes of org.openquark.cal.internal.machine.BasicOpTuple

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.