/* * 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. */ /* * MachineFunctionImpl.java * Creation date: Dec. 10, 2006 * By: Raymond Cypher */ package org.openquark.cal.internal.machine; import java.io.IOException; import java.util.Set; import org.openquark.cal.compiler.CompilerMessageLogger; import org.openquark.cal.compiler.CoreFunction; import org.openquark.cal.compiler.Expression; import org.openquark.cal.compiler.ModuleTypeInfo; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.compiler.TypeExpr; import org.openquark.cal.internal.serialization.ModuleSerializationTags; import org.openquark.cal.internal.serialization.RecordInputStream; import org.openquark.cal.internal.serialization.RecordOutputStream; import org.openquark.cal.internal.serialization.RecordInputStream.RecordHeaderInfo; import org.openquark.cal.machine.MachineFunction; /** * @author rcypher * */ public abstract class MachineFunctionImpl implements MachineFunction { private static final int serialSchema = 0; /** The CoreFunction being specialized for a specific machine. */ private CoreFunction coreFunction; /** Flag indicating that machine specific code has been generated. */ private boolean codeGenerated = false; /** Flag indicating transformation optimizations have been applied. */ private boolean optimized = false; /** * Construct a label from name and offset * @param coreFunction */ public MachineFunctionImpl(CoreFunction coreFunction) { if (coreFunction == null) { throw new IllegalArgumentException ("Unable to create MachineFunction due to null argument."); } this.coreFunction = coreFunction; } /** * Set the expression form for the associated function. * @param e */ public final void setExpression (Expression e) { coreFunction.setExpression(e); } // Zero arity constructor for serialization. protected MachineFunctionImpl() { } /** Return the qualified name for this label. * @return QualifiedName */ public final QualifiedName getQualifiedName () { return coreFunction.getName(); } /** * Return the name for this label * @return String */ public final String getName() { return getQualifiedName().getUnqualifiedName(); } /** * Returns the arity of the code associated with this label. * @return in The arity of the code associated with this label. */ public final int getArity () { return coreFunction.getNFormalParameters(); } /** * @return Returns the aliasOf. */ public final QualifiedName getAliasOf() { return coreFunction.getAliasOf (); } /** * @return True if the function contained a call to unsafeCoerce. */ public final boolean getHadUnsafeCoerce(){ return coreFunction.getHadUnsafeCoerce(); } /** * Mark the expression as having contained an unsafeCoerce call. */ public final void setHadUnsafeCoerce(){ coreFunction.setHadUnsafeCoerce(); } /** * @return true if this is a primitive function, false otherwise. */ public final boolean isPrimitiveFunction() { return coreFunction.isPrimitiveFunction(); } /** * @return true if this is a foreign function, false otherwise. */ public final boolean isForeignFunction () { return coreFunction.isForeignFunction(); } /** * @return true if this is a CAL function (i.e. not primitive and not foreign), false otherwise. */ public final boolean isCALFunction () { return coreFunction.isCALFunction(); } /** * @return true if this is a CAL Data Constructor. */ public final boolean isDataConstructor () { return coreFunction.isDataConstructor(); } /** * A CAF is a constant applicative form. * Currently zero arity CAL functions are CAFs but foreign functions are not. * This is because a zero arity foreign function can return a different value * each time it is evaluated (ex. a constructor). * @return true if this is a constant applicative form. */ public final boolean isCAF () { return getArity() == 0 && !isForeignFunction() && !isDataConstructor(); } /** * Return the timestamp associated with this entity. * @return long */ public final long getTimeStamp() { return coreFunction.getTimeStamp(); } /** * @return strictness info for the arguments. */ public final boolean[] getParameterStrictness() { return coreFunction.getParameterStrictness(); } /** * @return types of the arguments. */ public final TypeExpr[] getParameterTypes() { return coreFunction.getParameterTypes(); } /** * @return Returns the isTailRecursive flag. */ public final boolean isTailRecursive() { return coreFunction.isTailRecursive(); } /** * @return Returns the expressionForm. */ public final Expression getExpressionForm() { return coreFunction.getExpression(); } /** * @return Returns the parameterNames. */ public final String[] getParameterNames() { return coreFunction.getFormalParameters(); } @Override public final String toString () { StringBuilder sb = new StringBuilder(); sb.append(getCoreFunction().toString()); sb.append("alias = " + getAliasOf() + "\n"); sb.append("literalValue = " + getLiteralValue() + "\n"); sb.append("timeStamp = " + getTimeStamp() + "\n"); sb.append("isCAF = " + isCAF() + "\n"); sb.append("isCALFunction = " + isCALFunction() + "\n"); sb.append("isCodeGenerated = " + isCodeGenerated() + "\n"); sb.append("isDataConstructor = " + isDataConstructor() + "\n"); sb.append("isForAdjunct = " + isForAdjunct() + "\n"); sb.append("isForeignFunction = " + isForeignFunction() + "\n"); sb.append("isOptimized = " + isOptimized() + "\n"); sb.append("isPrimitiveFunction = " + isPrimitiveFunction() + "\n"); sb.append("isTailRecursive = " + isTailRecursive() + "\n"); return sb.toString(); } /** * @return Returns the connectedComponent. */ public final Set<String> getStronglyConnectedComponents() { return coreFunction.getStronglyConnectedComponents(); } /** * @param function * @return true if this is strongly connected to function. */ public final boolean isStronglyConnectedTo(String function) { return coreFunction.isStronglyConnectedTo(function); } /** * Derived classes can override this to generate appropriate disassembly. * @return the disassembled form of the function. */ public String getDisassembly () { return "Unable to disassemble function " + getQualifiedName() + "."; } /** * @return Returns the codeGenerated. */ public final boolean isCodeGenerated() { return codeGenerated; } /** * @param codeGenerated The codeGenerated to set. */ public final void setCodeGenerated(boolean codeGenerated) { this.codeGenerated = codeGenerated; } /** * @param aliasOf The aliasOf to set. */ public final void setAliasOf(QualifiedName aliasOf) { coreFunction.setAliasOf(aliasOf); } /** * @param connectedComponents (String set) The connectedComponents to set. Cannot be null. * {@inheritDoc} */ public void setStronglyConnectedComponents(Set<String> connectedComponents) { coreFunction.setStronglyConnectedComponents(connectedComponents); } /** * @param isTailRecursive The isTailRecursive to set. */ public final void setIsTailRecursive(boolean isTailRecursive) { coreFunction.setIsTailRecursive(isTailRecursive); } /** * @return Returns the coreFunction. */ public final CoreFunction getCoreFunction() { return coreFunction; } /** * Write this MachineFunction instance out to the RecordOutputStream. * @param s * @throws IOException */ public void write (RecordOutputStream s) throws IOException { s.startRecord (ModuleSerializationTags.MACHINE_FUNCTION, serialSchema); coreFunction.write (s); s.endRecord (); } /** * Reads this MachineFunction instance. * Read position in the stream is before record header. * @param s * @param mti * @param msgLogger the logger to which to log deserialization messages. * @throws IOException */ protected void read (RecordInputStream s, ModuleTypeInfo mti, CompilerMessageLogger msgLogger) throws IOException { // Load the record header and determine which actual class we are loading. RecordHeaderInfo rhi = s.findRecord(ModuleSerializationTags.MACHINE_FUNCTION); if (rhi == null) { throw new IOException ("Unable to find record header for MachineFunction."); } if (rhi.getSchema() > serialSchema) { throw new IOException("Saved schema is greater than current schema in MachineFunction."); } this.optimized = true; this.codeGenerated = true; coreFunction = CoreFunction.load(s, mti, msgLogger); s.skipRestOfRecord(); } /** * @return Returns the optimized. */ public final boolean isOptimized() { return optimized; } /** * Mark this function as being optimized. */ public final void setOptimized() { this.optimized = true; } /** * Get the number of formal arguments for this supercombinator. * Creation date: (3/9/00 3:30:22 PM) * @return int */ public final int getNFormalParameters() { return coreFunction.getNFormalParameters(); } /** * Get the type signature for the function. This is arguments and return type. * @return The function type signature. */ public final TypeExpr[] getType(){ return coreFunction.getType(); } /** * @return literal value if this supercombinator is defined as a literal value, null otherwise */ public final Object getLiteralValue() { return coreFunction.getLiteralValue(); } /** * @return true if this MachineFunction corresponds to an adjunct function. */ public final boolean isForAdjunct () { return coreFunction.isForAdjunct(); } /** * @return The result type of this function. */ public final TypeExpr getResultType () { return coreFunction.getResultType(); } /** * @return true if this CAL function is marked as being valid for * eager evaluation. */ public final boolean canFunctionBeEagerlyEvaluated () { return coreFunction.canFunctionBeEagerlyEvaluated(); } /** {@inheritDoc}*/ public final int compareTo (MachineFunction o) { return getName().compareTo(o.getName()); } @Override public final boolean equals (Object o) { if (o instanceof MachineFunction) { return getName().equals(((MachineFunction)o).getName()); } return false; } @Override public final int hashCode() { return getName().hashCode(); } }