/* * 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. */ /* * Node.java * Created: Sep 23, 2002 at 2:42:30 PM * By: Raymond Cypher */ package org.openquark.cal.internal.machine.g; import java.util.Collection; import org.openquark.cal.compiler.DataConstructor; import org.openquark.cal.runtime.CALExecutorException; import org.openquark.cal.runtime.CalValue; import org.openquark.cal.runtime.ErrorInfo; import org.openquark.cal.runtime.MachineType; /** * This is the Node class/interface * * The is the abstract base for the nodes used to construct the program graph. * Creation: Aug 12, 2002 at 12:44:15 PM * @author rcypher */ public abstract class Node extends CalValue { // static int nodeOrdCount = 0; // int nodeOrd; Node() { // nodeOrd = nodeOrdCount++; } protected abstract String toString(int n); /** * {@inheritDoc} */ @Override public abstract int debug_getNChildren(); /** * {@inheritDoc} */ @Override public abstract CalValue debug_getChild(int childN); /** * {@inheritDoc} */ @Override public abstract String debug_getNodeStartText(); /** * {@inheritDoc} */ @Override public abstract String debug_getNodeEndText(); /** * {@inheritDoc} */ @Override public abstract String debug_getChildPrefixText(int childN); /** * {@inheritDoc} */ @Override public final boolean debug_isIndirectionNode() { return hasIndirection(); } /** * Generate a string of the form '#<ordinal value>: <type name> */ protected String idString (int indent) { StringBuilder sp = new StringBuilder(); for (int i = 0; i < indent; ++i) { sp.append(" "); } Class<? extends Node> cl = getClass (); String name = cl.getName (); name = name.substring (name.lastIndexOf ('.')+1, name.length()); return sp.toString() + name; // return sp.toString() + "#" + nodeOrd + ", " + name; } protected abstract void addChildren(Collection<Node> c); protected void setIndirectionNode(Node n) { throw new UnsupportedOperationException("Setting indirection in bad node type. " + this.toString()); } protected void setParent (Node n) { } public int getOrdinalValue () { throw new UnsupportedOperationException("Can't call getTagValue for class: " + getClass().getName()); } public Object getValue() { throw new UnsupportedOperationException("Can only call getValue for values or data constructors."); } protected boolean hasIndirection() { return false; } Node getIndirectionNode () { return null; } /* * Functions to make the state changes. */ /** * Do Unwind state transition. */ protected void i_unwind(Executor e) throws CALExecutorException { throw new UnsupportedOperationException("Cannot unwind on node of type. " + this.toString()); } /** * Print */ protected void i_print(Executor e) throws CALExecutorException { throw new CALExecutorException.InternalException("i_print: bad node type on stack.", null); } /** * Do a split state transition. */ protected void i_split(Executor e, int n) throws CALExecutorException { //split state transitions are used for unpacking the arguments of //a data constructor (or data constructor like object such as an //integer value used in a case expression). Thus they are errors //unless there is a NVal or NConstr object on the stack throw new CALExecutorException.InternalException("i_split: bad node type on stack. " + this.toString (), null); } /** * Gets the field for the indicated data constructor value. * @param dataConstructor the data constructor expected to represent the value. * @param fieldIndex the index of the field to retrieve. * @param errorInfo The error information that identifies the source position of the selection. May be null. * @return The selected field * @throws CALExecutorException */ protected Node i_selectDCField(DataConstructor dataConstructor, int fieldIndex, ErrorInfo errorInfo) throws CALExecutorException { //select DC field is used for unpacking an argument of //a data constructor (or data constructor like object such as an //integer value used in a case expression). Thus they are errors //unless there is a NVal or NConstr object on the stack throw new CALExecutorException.InternalException("i_selectDCField: bad node type on stack. " + this.toString (), null); } protected void i_dispatch (Executor e, int k) throws CALExecutorException { // The general case. // <f:n1:n2:...:nk:r:S, G[f=AP m1 m2], Dispatch k:[], D> // => // <f:v1:v2:...:v(k-1):r:S, G[v1 = AP f n1 ], Unwind:[], D> // [vi = AP v(i-1), ni (1<i<k)] // [r = AP v(k-1) nk ] int si = e.stack.size () - 2; for (int i=1; i < k; ++i) { e.stack.set (si, new NAp (e.stack.get (si+1), e.stack.get(si--))); } NAp na = new NAp (e.stack.get (si + 1), e.stack.get (si)); e.stack.remove (si--); e.stack.get (si).setIndirectionNode (na); e.stack.set (si, na); e.stack.peek ().i_unwind (e); } /** * Do the Eval state transition. */ protected abstract void i_eval(Executor e) throws CALExecutorException; /** * Build an application of deepSeq */ protected abstract Node buildDeepSeqInternal(Node rhs) ; public final Node buildDeepSeq (Node rhs) { return buildDeepSeqInternal (rhs); } public Node getLeafNode () { return this; } /** * Apply this node to the given argument. * @param n * @return the application of this node to the argument. */ public Node apply (Node n) { return new NAp (this, n); } /** {@inheritDoc} */ @Override public final Node internalUnwrapOpaque() { if (this instanceof NValObject) { Object opaqueValue = ((NValObject)this).getValue(); if (opaqueValue instanceof Node) { return (Node)opaqueValue; } } return this; } @Override public final MachineType debug_getMachineType() { return MachineType.G; } }