/* * 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. */ /* * RTData.java * Created: Jan 22, 2002 at 2:16:12 PM * By: Luke Evans */ package org.openquark.cal.internal.runtime.lecc; import java.math.BigInteger; import org.openquark.cal.runtime.CalValue; /** * @author Luke Evans * * Base class for boxed primitive types. */ public abstract class RTData extends RTValue { /** * Add a package scope constructor to limit subclasses. */ RTData() { // Constructor declared to limit subclasses. } /** * Unwind this object. * @param ec * @return RTValue */ @Override protected final RTValue reduce(RTExecutionContext ec) { // Constructor applications are never reducible! return this; } /** * {@inheritDoc} */ @Override public final int debug_getNChildren() { return 0; } /** * {@inheritDoc} */ @Override public final CalValue debug_getChild(int childN) { throw new IndexOutOfBoundsException(); } /** * {@inheritDoc} */ @Override public abstract String debug_getNodeStartText(); /** * {@inheritDoc} */ @Override public final String debug_getNodeEndText() { return ""; } /** * {@inheritDoc} */ @Override public final String debug_getChildPrefixText(int childN) { throw new IndexOutOfBoundsException(); } // CAL_Short public static final class CAL_Short extends RTData { static private final CAL_Short[] cachedShorts = makeCache(); //holds -128 through 127 inclusive static private final CAL_Short[] makeCache() { CAL_Short[] cache = new CAL_Short[256]; for (int i = 0, cacheSize = cache.length; i < cacheSize; i++) { cache[i] = new CAL_Short((short)(i - 128)); } return cache; } private final short shortValue; private CAL_Short(short value) { super(); this.shortValue = value; } public static final CAL_Short make(short s) { if (s >= -128 && s <= 127) { return cachedShorts[s + 128]; } return new CAL_Short(s); } @Override public final short getShortValue () { return shortValue; } /** * See comment in RTValue.getOrdinalValue * @return the ordinal value associated with this instance */ @Override public final int getOrdinalValue() { return shortValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return Short.toString(shortValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.SHORT; } } // CAL_Byte public static final class CAL_Byte extends RTData { static private final CAL_Byte[] cachedBytes = makeCache(); //holds -128 through 127 inclusive static private final CAL_Byte[] makeCache() { CAL_Byte[] cache = new CAL_Byte[256]; for (int i = 0, cacheSize = cache.length; i < cacheSize; i++) { cache[i] = new CAL_Byte((byte)(i - 128)); } return cache; } private final byte byteValue; private CAL_Byte (byte value) { super(); this.byteValue = value; } public final static CAL_Byte make(byte value) { return cachedBytes[(int)value + 128]; } @Override public final byte getByteValue () { return byteValue; } /** * See comment in RTValue.getOrdinalValue * @return the ordinal value associated with this instance */ @Override public final int getOrdinalValue() { return byteValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return Byte.toString(byteValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.BYTE; } } // CAL_Float public static final class CAL_Float extends RTData { private final float floatValue; public CAL_Float(float value) { super(); this.floatValue = value; } public final static CAL_Float make(float value) { return new CAL_Float (value); } @Override public final float getFloatValue () { return floatValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return Float.toString(floatValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.FLOAT; } } // CAL_Long public static final class CAL_Long extends RTData { static private final CAL_Long[] cachedLongs = makeCache(); //holds -128 through 127 inclusive static private final CAL_Long[] makeCache() { CAL_Long[] cache = new CAL_Long[256]; for (int i = 0, cacheSize = cache.length; i < cacheSize; i++) { cache[i] = new CAL_Long(i - 128); } return cache; } private final long longValue; private CAL_Long(long value) { super(); this.longValue = value; } public static final CAL_Long make(long l) { if (l >= -128 && l <= 127) { return cachedLongs[(int)l + 128]; } return new CAL_Long(l); } @Override public final long getLongValue () { return longValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return Long.toString(longValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.LONG; } } // CAL_BigInteger public static final class CAL_Integer extends RTData { private BigInteger bigIntegerValue; public CAL_Integer (BigInteger value) { super(); this.bigIntegerValue = value; } public final static CAL_Integer make(BigInteger value) { return new CAL_Integer (value); } @Override public final BigInteger getIntegerValue () { return bigIntegerValue; } /** * Get the object wrapped by this instance. * @return Object */ @Override public final Object getOpaqueValue () { return bigIntegerValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return String.valueOf(bigIntegerValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.OBJECT; } } // CAL_Boolean public static abstract class CAL_Boolean extends RTData { public static final CAL_Boolean TRUE = new CAL_True(); public static final CAL_Boolean FALSE = new CAL_False(); @Override public abstract boolean getBooleanValue (); public final static CAL_Boolean make (boolean b) { if (b) { return TRUE; } else { return FALSE; } } public static final class CAL_True extends CAL_Boolean { private CAL_True() { } @Override public final boolean getBooleanValue () { return true; } /** * See comment in RTValue.getOrdinalValue * @return the ordinal value associated with this instance */ @Override public final int getOrdinalValue() { return 1; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return "true"; } } public static final class CAL_False extends CAL_Boolean { private CAL_False() { } @Override public final boolean getBooleanValue () { return false; } /** * See comment in RTValue.getOrdinalValue * @return the ordinal value associated with this instance */ @Override public final int getOrdinalValue() { return 0; } /** * @see org.openquark.cal.internal.runtime.lecc.RTValue#isLogicalTrue() */ @Override public final boolean isLogicalTrue() { return false; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return "false"; } } /** * Add a private constructor to prevent subclasses other than CAL_False and CAL_True. */ private CAL_Boolean() { // Constructor explicitly declared and made private to prevent instantiation. } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.BOOLEAN; } } /** * CAL_Integer implements integer data * @author LEvans */ public static final class CAL_Int extends RTData { static private final CAL_Int[] cachedIntegers = makeCache(); //holds -128 through 127 inclusive static private final CAL_Int[] makeCache() { CAL_Int[] cache = new CAL_Int[256]; for(int i = 0, cacheSize = cache.length; i < cacheSize; i++) { cache[i] = new CAL_Int(i - 128); } return cache; } private final int intValue; /** * Construct an CAL_Integer from its value * @param value the integer value */ private CAL_Int(int value) { super(); this.intValue = value; } public static final CAL_Int make(int i) { if (i >= -128 && i <= 127) { return cachedIntegers[i + 128]; } return new CAL_Int(i); } /** * Return the integer value for this object. * @return int */ @Override public final int getIntValue () { return intValue; } /** * See comment in RTValue.getOrdinalValue * @return the ordinal value associated with this instance */ @Override public final int getOrdinalValue() { return intValue; } //we do not want the runtime to have smarts about the relation between the java types int and java.lang.Integer //(and similarly between the other primitive Java types and their canonical Java boxed representation). //We previously added such facilities so that certain constructions using Prelude.unsafeCoerce would work. //However, we decided to tighten the semantics of what unsafeCoerce can do- it cannot modify the value in any //way, it is only a directive for coercing the compiler to accept a potentially type-unsafe construct. // public final Object getOpaqueValue () { // return JavaPrimitives.makeInteger(intValue); // } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return Integer.toString(intValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.INT; } } /** * CAL_String implements string data * @author RCypher */ public static final class CAL_String extends RTData { private final String stringValue; /** * Construct an CAL_Integer from its value * @param value the integer value */ public CAL_String (String value) { super(); this.stringValue = value; } public static final CAL_String make(String value) { return new CAL_String (value); } /** * Get the string value wrapped by this instance. * @return String */ @Override public final String getStringValue() { return stringValue; } /** * Get the object wrapped by this instance. * @return Object */ @Override public final Object getOpaqueValue () { return stringValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { //note that the reason that we are not putting double quotes around the String i.e. "abc", is that the CAL_String type //does not *only* represent Prelude.String, but rather any type whose Java implementation type is the primitive type //java.lang.String. We highlight this difference by using the default java implementation of String.valueOf(). //Note: if you want to change this in the future, to be consistent, one must change all the other places where //StringBuilder.append(String) is called, such as in the custom generated debug_getNodeStartText methods for data types and //strict application nodes. Also, CAL_Opaque can sometimes hold a String value, so one needs to check and update that //case as well. return String.valueOf(stringValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.OBJECT; } } /** * CAL_Double implements double precision floating point number data * @author LEvans */ public static final class CAL_Double extends RTData { private final double doubleValue; /** * Construct an CAL_Integer from its value * @param value the integer value */ public CAL_Double(double value) { super(); this.doubleValue = value; } public static final CAL_Double make(double value) { return new CAL_Double(value); } /** * Get the double value wrapped by this instance. * @return double */ @Override public final double getDoubleValue () { return doubleValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { return Double.toString(doubleValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.DOUBLE; } } public static final class CAL_Char extends RTData { static private final CAL_Char[] cachedCharacters = makeCache(); //holds 0 through 127 inclusive static private final CAL_Char[] makeCache() { CAL_Char[] cache = new CAL_Char[128]; for (int i = 0, cacheSize = cache.length; i < cacheSize; i++) { cache[i] = new CAL_Char((char)i); } return cache; } private final char charValue; /** * Construct an CAL_Integer from its value * @param value the integer value */ private CAL_Char (char value) { super(); this.charValue = value; } public static final CAL_Char make(char c) { if (c <= 127) { return cachedCharacters[(int)c]; } return new CAL_Char(c); } /** * Get the char value wrapped by this instance. * @return char */ @Override public final char getCharValue () { return charValue; } /** * See comment in RTValue.getOrdinalValue * @return the ordinal value associated with this instance */ @Override public final int getOrdinalValue () { return charValue; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { //note that the reason that we are not putting single quotes around the char i.e. 'a', is that the CAL_Char type //does not *only* represent Prelude.Char, but rather any type whose Java implementation type is the primitive type //char. We highlight this difference by using the default java.lang.Character.toString() implementation. //Note: if you want to change this in the future, to be consistent, one must change all the other places where //StringBuilder.append(char) is called, such as in the custom generated debug_getNodeStartText methods for data types and //strict application nodes. return Character.toString(charValue); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.CHAR; } } /** * CAL_Opaque implements the wrapper for opaque data types. * @author RCypher */ public static final class CAL_Opaque extends RTData { private Object value; /** * Construct an CAL_Integer from its value * @param value the integer value */ public CAL_Opaque (Object value) { super(); this.value = value; } public static final CAL_Opaque make(Object value) { return new CAL_Opaque (value); } /** * Get the object wrapped by this instance. * @return Object */ @Override public final Object getOpaqueValue () { return value; } /** * The BigInteger value held by this CAL_Opaque. Normally these are cloaked in * CAL_Integer values, but sometimes not. * @return BigInteger */ @Override public final BigInteger getIntegerValue () { return (BigInteger)value; } /** * The BigInteger value held by this CAL_Opaque. Normally these are cloaked in * CAL_String values, but sometimes not. * @return BigInteger */ @Override public final String getStringValue () { return (String)value; } /** * {@inheritDoc} */ @Override public final String debug_getNodeStartText() { //note that the reason that we are not putting single quotes around the char i.e. 'a', is that the CAL_Char type //does not *only* represent Prelude.Char, but rather any type whose Java implementation type is the primitive type //char. We highlight this difference by using the default java.lang.Character.toString() implementation. //Note: if you want to change this in the future, to be consistent, one must change all the other places where //StringBuilder.append(char) is called, such as in the custom generated debug_getNodeStartText methods for data types and //strict application nodes. return String.valueOf(value); } /** * {@inheritDoc} */ @Override public final DataType getDataType() { return DataType.OBJECT; } } }