/* * 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. */ /* * AlgebraicCALValue.java * Creation date (Aug 1, 2002). * By: Bo Ilic */ package org.openquark.cal.foreignsupport.module.Prelude; import java.util.List; import org.openquark.cal.compiler.QualifiedName; /** * Base class for supporting CAL types with derived instances of Prelude.Inputable or Prelude.Outputable. * Values of such types will output to a Java object of type AlgebraicValue. * * @author Bo Ilic */ public abstract class AlgebraicValue { /** CAL name of the data constructor at the root of the value graph. */ private final QualifiedName dataConstructorName; /** index of the data constructor at the root of the value graph. */ private final int dataConstructorOrdinal; private AlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal) { if (dataConstructorName == null) { throw new NullPointerException("argument dataConstructorName cannot be null."); } if (dataConstructorOrdinal < 0) { throw new IllegalArgumentException(); } this.dataConstructorName = dataConstructorName; this.dataConstructorOrdinal = dataConstructorOrdinal; } /** * Zero-argument-datacons factory method for AlgebraicValue objects. * * @param dataConstructorName QualifiedName of the data constructor that constructs this value * @param dataConstructorOrdinal Index of the data constructor that constructs this value * @return An AlgebraicValue object that represents the value returned by the specified data constructor */ public static AlgebraicValue makeZeroArgumentAlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal) { return new ZeroArgumentAlgebraicValue(dataConstructorName, dataConstructorOrdinal); } /** * Zero-argument-datacons factory method for AlgebraicValue objects. * * @param dataConstructorName Fully-qualified name of the data constructor (that constructs this value (eg "Cal.Core.Prelude.Just") * @param dataConstructorOrdinal Ordinal of the data constructor that constructs this value * @return An AlgebraicValue object that represents the value returned by the specified data constructor */ public static AlgebraicValue makeZeroArgumentAlgebraicValue(String dataConstructorName, int dataConstructorOrdinal) { return makeZeroArgumentAlgebraicValue(QualifiedName.makeFromCompoundName(dataConstructorName), dataConstructorOrdinal); } /** * Single-argument-datacons factory method for AlgebraicValue objects. * * @param dataConstructorName QualifiedName of the data constructor that constructs this value * @param dataConstructorOrdinal Index of the data constructor that constructs this value * @param argumentValue The single argument to the data constructor * @return An AlgebraicValue object that represents the value returned by applying the specified argument to the specified data constructor */ public static AlgebraicValue makeSingleArgumentAlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal, Object argumentValue) { return new SingleArgumentAlgebraicValue(dataConstructorName, dataConstructorOrdinal, argumentValue); } /** * Single-argument-datacons factory method for AlgebraicValue objects. * * @param dataConstructorName Fully-qualified name of the data constructor (that constructs this value (eg "Cal.Core.Prelude.Just") * @param dataConstructorOrdinal Ordinal of the data constructor that constructs this value * @param argumentValue The single argument to the data constructor * @return An AlgebraicValue object that represents the value returned by applying the specified argument to the specified data constructor */ public static AlgebraicValue makeSingleArgumentAlgebraicValue(String dataConstructorName, int dataConstructorOrdinal, Object argumentValue) { return makeSingleArgumentAlgebraicValue(QualifiedName.makeFromCompoundName(dataConstructorName), dataConstructorOrdinal, argumentValue); } /** * Factory method for general AlgebraicValue objects. * * @param dataConstructorName QualifiedName of the data constructor that constructs this value * @param dataConstructorOrdinal Index of the data constructor that constructs this value * @param argumentValuesList List (Object) of arguments to the data constructor * @return An AlgebraicValue object that represents the value returns by applying the specified arguments to the specified data constructor */ public static AlgebraicValue makeGeneralAlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal, List<?> argumentValuesList) { switch(argumentValuesList.size()) { case 0: return new ZeroArgumentAlgebraicValue(dataConstructorName, dataConstructorOrdinal); case 1: return new SingleArgumentAlgebraicValue(dataConstructorName, dataConstructorOrdinal, argumentValuesList.get(0)); default: return new GeneralAlgebraicValue(dataConstructorName, dataConstructorOrdinal, argumentValuesList); } } /** * Factory method for general AlgebraicValue objects. * * @param dataConstructorName Fully-qualified name of the data constructor (that constructs this value (eg "Cal.Core.Prelude.Just") * @param dataConstructorOrdinal Ordinal of the data constructor that constructs this value * @param argumentValues List (Object) of arguments to the data constructor * @return An AlgebraicValue object that represents the value returned by applying the specified arguments to the specified data constructor */ public static AlgebraicValue makeGeneralAlgebraicValue(String dataConstructorName, int dataConstructorOrdinal, List<?> argumentValues) { return makeGeneralAlgebraicValue(QualifiedName.makeFromCompoundName(dataConstructorName), dataConstructorOrdinal, argumentValues); } /** @return name of the data constructor corresponding to this algebraic value. */ public final QualifiedName getName() { return dataConstructorName; } /** @return name of the data constructor corresponding to this value expanded to a String. */ public final String getDataConstructorName() { return getName().getQualifiedName(); } /** @return ordinal of the data constructor corresponding to this value */ public final int getDataConstructorOrdinal() { return dataConstructorOrdinal; } /** @return number of arguments that this data constructor is holding. */ public abstract int getNArguments(); /** * @param argN zero-based index to an argument held by this data constructor. * @return argument value corresponding the argNth argument. */ public abstract Object getNthArgument(int argN); /** * {@inheritDoc} */ @Override public final String toString() { int nValues = getNArguments(); if (nValues == 0) { return getDataConstructorName(); } StringBuilder result = new StringBuilder("("); result.append(getDataConstructorName()); for (int i = 0; i < nValues; ++i) { result.append(' ').append(getNthArgument(i)); } result.append(')'); return result.toString(); } /** * This class can represent any algebraic value. For certain special cases * (eg, for data constructors that take no arguments) it is less efficient * than the more specialized AlgebraicValue subclasses. * * Creation date: (Jul 19, 2005) * @author Jawright */ private static final class GeneralAlgebraicValue extends AlgebraicValue { /** arguments to which the data constructor is applied. */ private final Object[] argumentValues; private static final Object[] NO_ARGUMENTS = new Object[0]; /** * @param dataConstructorName CAL name of the data constructor that wraps this value at the outermost level. * @param dataConstructorOrdinal the ordinal of the data constructor that wraps this value at the outermost level. * @param argumentValuesList arguments to which the data constructor is applied. * @throws NullPointerException if dataConstructorName is null. */ public GeneralAlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal, List<?> argumentValuesList) { super (dataConstructorName, dataConstructorOrdinal); if (argumentValuesList == null) { this.argumentValues = NO_ARGUMENTS; } else { argumentValues = argumentValuesList.toArray(NO_ARGUMENTS); } } /** * {@inheritDoc} */ @Override public int getNArguments() { return argumentValues.length; } /** * {@inheritDoc} */ @Override public Object getNthArgument(int argN) { return argumentValues[argN]; } } /** * This class can represent any algebraic value whose data constructor does not * accept any arguments. * * Creation date: (Jul 20, 2005) * @author Jawright */ private static final class ZeroArgumentAlgebraicValue extends AlgebraicValue { /** * Construct a ZeroArgumentAlgebraicValue. Note that no arguments are * accepted since the data constructor has no parameters. * * @param dataConstructorName Name of the data constuctor * @param dataConstructorOrdinal Ordinal of the data constructor */ public ZeroArgumentAlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal) { super(dataConstructorName, dataConstructorOrdinal); } /** * {@inheritDoc} */ @Override public int getNArguments() { return 0; } /** * {@inheritDoc} */ @Override public Object getNthArgument(int n) { throw new IndexOutOfBoundsException(); } } /** * This class can represent any algebraic value whose data constructor accepts * exactly 1 parameter. * * Creation date: (Jul 20, 2005) * @author Jawright */ private static final class SingleArgumentAlgebraicValue extends AlgebraicValue { private final Object argumentValue; /** * Construct a SingleArgumentAlgebraicValue. * * @param dataConstructorName Name of the data constuctor * @param dataConstructorOrdinal Ordinal of the data constructor */ public SingleArgumentAlgebraicValue(QualifiedName dataConstructorName, int dataConstructorOrdinal, Object argumentValue) { super (dataConstructorName, dataConstructorOrdinal); this.argumentValue = argumentValue; } /** * {@inheritDoc} */ @Override public int getNArguments() { return 1; } /** * {@inheritDoc} */ @Override public Object getNthArgument(int n) { if(n != 0) { throw new IndexOutOfBoundsException(); } return argumentValue; } } }