338 lines
11 KiB
Java
338 lines
11 KiB
Java
|
// ESValue.java
|
||
|
// FESI Copyright (c) Jean-Marc Lugrin, 1999
|
||
|
//
|
||
|
// This program is free software; you can redistribute it and/or
|
||
|
// modify it under the terms of the GNU Lesser General Public
|
||
|
// License as published by the Free Software Foundation; either
|
||
|
// version 2 of the License, or (at your option) any later version.
|
||
|
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
// Lesser General Public License for more details.
|
||
|
|
||
|
// You should have received a copy of the GNU Lesser General Public
|
||
|
// License along with this library; if not, write to the Free Software
|
||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
package FESI.Data;
|
||
|
|
||
|
import java.util.Enumeration;
|
||
|
|
||
|
import FESI.Exceptions.*;
|
||
|
import FESI.Interpreter.Evaluator;
|
||
|
|
||
|
/**
|
||
|
* All EcmaScript values are subclasses of this class.
|
||
|
* The ESValue support many operations which may not be
|
||
|
* implemented by all type (and then generate an error),
|
||
|
* to simplify type checking.
|
||
|
* <P>ESReference are currently not value - see ESReference.
|
||
|
*/
|
||
|
public abstract class ESValue {
|
||
|
|
||
|
// Codes for the getTypeOf, used to implement "=="
|
||
|
public static final int EStypeUndefined = 1;
|
||
|
public static final int EStypeNull = 2;
|
||
|
public static final int EStypeBoolean = 3;
|
||
|
public static final int EStypeNumber = 4;
|
||
|
public static final int EStypeString = 5;
|
||
|
public static final int EStypeObject = 6;
|
||
|
|
||
|
// The following routines access the value as a primitive type. They are
|
||
|
// the prefered way to access the value of a primitive type or the default
|
||
|
// value of an object if its type is known.
|
||
|
// If the object is a reference, it will be dereferenced until a value is
|
||
|
// found, this may generate an error or return a dummy value.
|
||
|
//
|
||
|
// toString() is considered part of these data access routine, however
|
||
|
// it may never fail. It is implemented as described in 9.8.
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns a detailed description of the value, intended for debugging.
|
||
|
* (toString returns the official string representation, as defined in 9.8).
|
||
|
*
|
||
|
* @return the detailled information
|
||
|
*/
|
||
|
abstract public String toDetailString();
|
||
|
|
||
|
/**
|
||
|
* Return a Java object which is the object to pass to Java routines
|
||
|
* called by FESI. This may be the corresponding Java object (for
|
||
|
* example the String), or a wrapper object. When received back from
|
||
|
* a Java routine, an equivallent (but probably not identical) object
|
||
|
* must be built.
|
||
|
*
|
||
|
* @return a Java object equivallent to the EcmaScript object.
|
||
|
*/
|
||
|
public abstract Object toJavaObject();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Return the double value of this ESValue as defined in 9.3, throw an
|
||
|
* exception if not defined.
|
||
|
*
|
||
|
* @return a double
|
||
|
* @exception EcmaScriptException Thrown because by default this is not supported
|
||
|
*/
|
||
|
public double doubleValue() throws EcmaScriptException {
|
||
|
throw new EcmaScriptException("Conversion to double unsupported by " + this);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Return the boolean value of this ESValue as defined in 9.2, throw an
|
||
|
* exception if not defined.
|
||
|
*
|
||
|
* @return a boolean
|
||
|
* @exception EcmaScriptException Thrown because by default this is not supported
|
||
|
*/
|
||
|
public boolean booleanValue() throws EcmaScriptException {
|
||
|
throw new EcmaScriptException("Conversion to boolean unsupported by " + this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the EcmaScript object of this ESValue as definined in 9.9, throw
|
||
|
* an exception if not defined.
|
||
|
*
|
||
|
* @param evaluator The evaluator object
|
||
|
* @return an ESObject
|
||
|
* @exception EcmaScriptException Thrown because by default this is not supported
|
||
|
*/
|
||
|
public ESValue toESObject(Evaluator evaluator) throws EcmaScriptException {
|
||
|
throw new EcmaScriptException("Conversion to object unsupported by " + this);
|
||
|
}
|
||
|
|
||
|
// The following routines are derived from the doubleValue of the
|
||
|
// ESvalue. They may be overriden for efficiency by classes which
|
||
|
// contain an integer or other equivallent.
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Return the Integer value, as defined in 9.4.
|
||
|
*
|
||
|
* @return An integer inside a double
|
||
|
* @exception EcmaScriptException Not thrown
|
||
|
*/
|
||
|
public double toInteger() throws EcmaScriptException {
|
||
|
double value = this.doubleValue();
|
||
|
if (Double.isNaN(value)) {
|
||
|
return 0.0;
|
||
|
} else if ((value == 0.0) ||
|
||
|
Double.isInfinite(value)) {
|
||
|
return value;
|
||
|
} else {
|
||
|
return (double)((long) value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the 32 bit integer, as defined in 9.5
|
||
|
*
|
||
|
* @return The signed 32 bit integer
|
||
|
* @exception EcmaScriptException Not thrown
|
||
|
*/
|
||
|
public int toInt32() throws EcmaScriptException {
|
||
|
double value = this.toInteger();
|
||
|
return (int) value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returned the unsigned 32 bit integer (9.6). Currently
|
||
|
* implemented as toInt32 !
|
||
|
*
|
||
|
* @return The integer
|
||
|
* @exception EcmaScriptException Not thrown
|
||
|
*/
|
||
|
public int toUInt32() throws EcmaScriptException {
|
||
|
double value = this.toInteger();
|
||
|
return (int) value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the unsigned 16 bit integer (9.7). Currently
|
||
|
* ignore the sign issue.
|
||
|
*
|
||
|
* @return The unsigned as a short
|
||
|
* @exception EcmaScriptException Not thrown
|
||
|
*/
|
||
|
public short toUInt16() throws EcmaScriptException {
|
||
|
double value = this.toInteger();
|
||
|
return (short) value;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Convertion to EcmaScript primitive type - rebuild the primitive type based
|
||
|
// on the convertion to the Java primitive type. May be overriden by a subclass
|
||
|
// for efficiency purpose (especially if it does not require a conversion).
|
||
|
|
||
|
// In fact on toESNumber is used (to implement the operator +), and this
|
||
|
// is a very minor performance enhancement - so the routine could be
|
||
|
// easily supressed
|
||
|
|
||
|
/**
|
||
|
* Convert the value to an EcmaScript boolean (9.2) if possible
|
||
|
*
|
||
|
* @return The EcmaScript boolean value
|
||
|
* @exception EcmaScriptException Not thrown
|
||
|
*/
|
||
|
public ESValue toESBoolean() throws EcmaScriptException {
|
||
|
return ESBoolean.makeBoolean(this.booleanValue());
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Convert the value to an EcmaScript string (9.8) if possible
|
||
|
*
|
||
|
* @return The EcmaScript string value (there is always one!)
|
||
|
*/
|
||
|
public ESValue toESString() {
|
||
|
return new ESString(this.toString());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Convert the value to an EcmaScript number (9.3) if possible
|
||
|
*
|
||
|
* @return The EcmaScript number value
|
||
|
* @exception EcmaScriptException From doubleValue
|
||
|
*/
|
||
|
public ESValue toESNumber() throws EcmaScriptException {
|
||
|
double d = this.doubleValue();
|
||
|
return new ESNumber(d);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Provide support to easily distinguish primitive values from other, and
|
||
|
// to convert values to primitive value. If the desired type is known
|
||
|
// the direct conversion routines are prefered.
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Return true if the value is a built-in primitive
|
||
|
*
|
||
|
* @return true if a primitive
|
||
|
*/
|
||
|
abstract public boolean isPrimitive();
|
||
|
|
||
|
/**
|
||
|
* Transform to a primitive as described in 9.1
|
||
|
*
|
||
|
* @return A primitive value
|
||
|
* @exception EcmaScriptException If conversion is impossible
|
||
|
*/
|
||
|
abstract public ESValue toESPrimitive() throws EcmaScriptException;
|
||
|
|
||
|
/**
|
||
|
* Transform to a primitive as described in 9.1, with a specified hint
|
||
|
*
|
||
|
* @param preferedType the prefered type to return
|
||
|
* @return a primitive value
|
||
|
* @exception EcmaScriptException If conversion is impossible
|
||
|
*/
|
||
|
abstract public ESValue toESPrimitive(int preferedType) throws EcmaScriptException;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// [[Call]] support (to ease check of type)
|
||
|
public ESValue callFunction(ESObject thisObject,
|
||
|
ESValue[] arguments)
|
||
|
throws EcmaScriptException {
|
||
|
throw new EcmaScriptException("Function called on non object: " + this);
|
||
|
}
|
||
|
|
||
|
// [[Construct]] support (to ease check of type)
|
||
|
public ESObject doConstruct(ESObject thisObject,
|
||
|
ESValue[] arguments)
|
||
|
throws EcmaScriptException {
|
||
|
throw new EcmaScriptException("'new' called on non object: " + this);
|
||
|
}
|
||
|
|
||
|
// abstract public ESValue doNewObject();
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Information routine to check if a value is a number (for array indexing)
|
||
|
* if true, must implement conversions to double and int without evaluator.
|
||
|
* @return true if a number.
|
||
|
*/
|
||
|
public boolean isNumberValue() {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Information routine to check if a value is a string
|
||
|
* if true, must implement toString without a evaluator.
|
||
|
* @return true if a String (ESString or StringPrototype).
|
||
|
*/
|
||
|
public boolean isStringValue() {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Information routine to check if a value is a boolean
|
||
|
* if true, must implement booleanValue without a evaluator.
|
||
|
* @return true if a boolean (ESBoolean or BooleanPrototype).
|
||
|
*/
|
||
|
public boolean isBooleanValue() {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return a code indicating the type of the object for the implementation
|
||
|
* of the "==" operator.
|
||
|
*
|
||
|
* @return A type code
|
||
|
*/
|
||
|
public abstract int getTypeOf();
|
||
|
|
||
|
/**
|
||
|
* Return the name of the type of the object for the typeof operator
|
||
|
*
|
||
|
* @return The name of the type as a String
|
||
|
*/
|
||
|
public abstract String getTypeofString();
|
||
|
|
||
|
// Support to list description of objects
|
||
|
|
||
|
/**
|
||
|
* Return true if the value is composite (even if not an
|
||
|
* object). A composite value can be examined by getAllDescriptions.
|
||
|
* A composite value may have no component!
|
||
|
*
|
||
|
* @return true if composite
|
||
|
*/
|
||
|
abstract public boolean isComposite();
|
||
|
|
||
|
/**
|
||
|
* Return an enumeration of all description of elements of this
|
||
|
* value (for example properties of an object).
|
||
|
*
|
||
|
* @return Enumerator of all components or NULL.
|
||
|
*/
|
||
|
public Enumeration getAllDescriptions() {return null;}
|
||
|
|
||
|
/**
|
||
|
* Returns a full description of the value, with the specified name.
|
||
|
*
|
||
|
* @param name The name of the value to describe
|
||
|
*
|
||
|
* @return the description of this value
|
||
|
*/
|
||
|
abstract public ValueDescription getDescription(String name);
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns a full description of the unnamed value.
|
||
|
*
|
||
|
* @return the description of this value
|
||
|
*/
|
||
|
public ValueDescription getDescription() {
|
||
|
return getDescription(null);
|
||
|
}
|
||
|
}
|