helma/src/FESI/Interpreter/Evaluator.java
hns ee13186158 This commit was generated by cvs2svn to compensate for changes in r4,
which included commits to RCS files with non-trunk default branches.
2000-12-29 17:58:10 +00:00

1060 lines
37 KiB
Java

// Evaluator.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.Interpreter;
import FESI.Exceptions.*;
import FESI.Parser.*;
import FESI.AST.*;
import FESI.Extensions.Extension;
import FESI.jslib.*;
import FESI.Data.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.StringTokenizer;
import java.io.*;
import java.util.zip.*;
/**
* Defines the evaluation interface and contains the evaluation context.
* <P><B>Important:</B> This object is also used as the synchronization
* object - all entries into the evaluation process must be synchronized
* on the evaluator, as the inside of the evaluator is not synchronized
* for speed reasons.
*/
public class Evaluator {
// used to stop thread, 06.12.99 Hannes Wallnoefer
public volatile Thread thread;
private static String eol = System.getProperty("line.separator", "\n");
/**
* Return the version identifier of the interpreter
*/
public static String getVersion() {
return "1.1.4 (30-Jan-2000)";
}
/**
* Return the welcome text (including copyright and version)
* of the interpreter (as two lines)
*/
public static String getWelcomeText() {
return
"FESI (pronounced like 'fuzzy'): an EcmaScript Interpreter" + eol +
"Copyright (c) Jean-Marc Lugrin, 1998 - Version: " + Evaluator.getVersion();
}
private boolean debugParse = false;
// All privileged objects of interest of the evaluator
private GlobalObject globalObject = null;
private ESObject objectPrototype = null;
private ESObject functionPrototype = null;
private ESObject functionObject = null;
private ESObject stringPrototype = null;
private ESObject numberPrototype = null;
private ESObject booleanPrototype = null;
private ESObject arrayPrototype = null;
private ESObject datePrototype = null;
private ESObject packageObject = null;
// Current environment
private ScopeChain theScopeChain = null;
private ESObject currentVariableObject = null;
private ESObject currentThisObject = null;
// Visitors used for interpretation
private EcmaScriptFunctionVisitor functionDeclarationVisitor = null;
private EcmaScriptVariableVisitor varDeclarationVisitor = null;
//private EcmaScriptEvaluateVisitor evaluationVisitor = null;
// List of loaded extensions
private Hashtable extensions = null;
/**
* Reset the evaluator, forgetting all global definitions and loaded extensions
*/
protected void reset() {
functionDeclarationVisitor = new EcmaScriptFunctionVisitor(this);
varDeclarationVisitor = new EcmaScriptVariableVisitor(this);
// evaluationVisitor = new EcmaScriptEvaluateVisitor(this);
globalObject = GlobalObject.makeGlobalObject(this);
packageObject = new ESPackages(this);
extensions = new Hashtable(); // forget extensions
}
/**
* Create a new empty evaluator
*/
public Evaluator () {
reset();
}
/**
* Get the variable visitor of this evaluator
* @return the Variable visitor
*/
public EcmaScriptVariableVisitor getVarDeclarationVisitor() {
return varDeclarationVisitor;
}
//------------------------------------------------------------
// Access to special objects of the environment
//------------------------------------------------------------
/**
* Get the this object of this evaluator
* @return the this object
*/
public ESObject getThisObject() {
return currentThisObject;
}
/**
* Get the global object of this evaluator
* @return the global object
*/
public GlobalObject getGlobalObject() {
return globalObject;
}
/**
* Set the debug mode for the parser
* @param dp true to set debug mode on
*/
public void setDebugParse(boolean dp) {
debugParse = dp;
}
/**
* Return the debug state for the parser
* @return true if debug on
*/
public boolean isDebugParse() {
return debugParse;
}
/**
* Set the object prototype object
* <P>Used only by initilization code
* @param o the object
*/
public void setObjectPrototype(ESObject o) {
objectPrototype = o;
}
/**
* Get the Object prototype object
* @return the ESObject
*/
public ESObject getObjectPrototype() {
return objectPrototype;
}
/**
* Set the Function prototype object
* <P>Used only by initilization code
* @param o the object
*/
public void setFunctionPrototype(ESObject o) {
functionPrototype = o;
}
/**
* Get the Function prototype object
* @return the ESObject
*/
public ESObject getFunctionPrototype() {
return functionPrototype;
}
/**
* Set the Function object
* <P>Used only by initilization code
* @param o the object
*/
public void setFunctionObject(ESObject o) {
functionObject = o;
}
/**
* Get the Function object
* @return the ESObject
*/
public ESObject getFunctionObject() {
return functionObject;
}
/**
* Set the String object prototype
* <P>Used only by initilization code
* @param o the object
*/
public void setStringPrototype(ESObject o) {
stringPrototype = o;
}
/**
* Get the String prototype object
* @return the ESObject
*/
public ESObject getStringPrototype() {
return stringPrototype;
}
/**
* Set the Number object prototpe
* <P>Used only by initilization code
* @param o the object
*/
public void setNumberPrototype(ESObject o) {
numberPrototype = o;
}
/**
* Get the Number prototype object
* @return the ESObject
*/
public ESObject getNumberPrototype() {
return numberPrototype;
}
/**
* Set the Boolean object prototype
* <P>Used only by initilization code
* @param o the object
*/
public void setBooleanPrototype(ESObject o) {
booleanPrototype = o;
}
/**
* Get the Boolean prototype object
* @return the ESObject
*/
public ESObject getBooleanPrototype() {
return booleanPrototype;
}
/**
* Set the Array prototype object
* <P>Used only by initilization code
* @param o the object
*/
public void setArrayPrototype(ESObject o) {
arrayPrototype = o;
}
/**
* Get the Array prototype object
* @return the ESObject
*/
public ESObject getArrayPrototype() {
return arrayPrototype;
}
/**
* Set the Date object prototype
* <P>Used only by initilization code
* @param o the object
*/
public void setDatePrototype(ESObject o) {
datePrototype = o;
}
/**
* Get the Date prototype object
* @return the ESObject
*/
public ESObject getDatePrototype() {
return datePrototype;
}
/**
* Get the Package object
* @return the ESObject
*/
public ESObject getPackageObject() {
return packageObject;
}
//------------------------------------------------------------
// Extension support
//------------------------------------------------------------
/**
* Get a loaded extension by name
* @param name Extension to look up
* @return the extension or null if not loaded
*/
public Extension getExtension(String name) {
return (Extension) extensions.get(name);
}
/**
* Get the list of all extensions
* @return The extensions enumnerator
*/
public Enumeration getExtensions() {
return extensions.keys();
}
/**
* Add an extension by name, load it if not already loaded
* @param name the name of the extension to load
* @return the loaded object or null in case of error
* @exception Error ini initalizing the extension
*/
public Object addExtension(String name) throws EcmaScriptException {
Object extension = getExtension(name);
if (extension == null) {
try {
extension = Class.forName(name).newInstance();
if (extension instanceof Extension) {
((Extension) extension).initializeExtension(this);
} else if (extension instanceof JSExtension) {
GlobalObject go = this.getGlobalObject();
JSGlobalWrapper jgo = new JSGlobalWrapper(go,this);
try {
((JSExtension) extension).initializeExtension(jgo);
} catch (JSException e) {
return null;
}
} else {
return null;
}
extensions.put(name, extension);
} catch (ClassNotFoundException e) { // return null
extension = null;
} catch (NoClassDefFoundError e) { // return null
extension = null;
} catch (IllegalAccessException e) { // return null
extension = null;
} catch (InstantiationException e) { // return null
extension = null;
}
}
return extension;
}
/**
* Add an extension by name, load it if not already loaded.
* Generate an error if not found
* @param name the name of the extension to load
* @return the loaded object
* @exception EcmaScriptException if the extension cannot be loaded or error during initilization
*/
public Object addMandatoryExtension(String name) throws EcmaScriptException {
Object extension = getExtension(name);
if (extension == null) {
try {
extension = Class.forName(name).newInstance();
if (extension instanceof Extension) {
((Extension) extension).initializeExtension(this);
} else if (extension instanceof JSExtension) {
GlobalObject go = this.getGlobalObject();
JSGlobalWrapper jgo = new JSGlobalWrapper(go,this);
try {
((JSExtension) extension).initializeExtension(jgo);
} catch (JSException e) {
throw new EcmaScriptException("Error initializing extension " + name, e);
}
} else {
throw new EcmaScriptException("Extenstion object " + name + " of wrong type " + extension.getClass());
}
extensions.put(name, extension);
} catch (ClassNotFoundException e) {
throw new EcmaScriptException("Error loading extension " + name, e);
} catch (NoClassDefFoundError e) {
throw new EcmaScriptException("Error loading extension " + name, e);
} catch (IllegalAccessException e) {
throw new EcmaScriptException("Error loading extension " + name, e);
} catch (InstantiationException e) {
throw new EcmaScriptException("Error loading extension " + name, e);
}
}
return extension;
}
/**
* Add an initialized extension.
* Generate an error if not found
* @param name the name of the extension to load
* @param extension The extension object
* @return the loaded object
* @exception EcmaScriptException if the extension cannot be loaded or error during initilization
*/
public Object addMandatoryExtension(String name,FESI.jslib.JSExtension extension) throws EcmaScriptException {
GlobalObject go = this.getGlobalObject();
JSGlobalWrapper jgo = new JSGlobalWrapper(go,this);
try {
((JSExtension) extension).initializeExtension(jgo);
} catch (JSException e) {
throw new EcmaScriptException("Error initializing extension " + name, e);
}
extensions.put(name, extension);
return extension;
}
/**
* Get a reference to an indentifier (when its hash code is not known)
* @param identifier The name of the variable
* @return A reference object
*/
public ESReference getReference(String identifier) throws EcmaScriptException {
return theScopeChain.getReference(identifier);
}
/**
* Get a reference to an indentifier (when its hash code is known)
* @param identifier The name of the variable
* @param hash Its hash code (must be exact!)
* @return A reference object
*/
public ESReference getReference(String identifier,int hash) throws EcmaScriptException {
return theScopeChain.getReference(identifier, hash);
}
/**
* Get the value of a variable in the scope chain (when its hash code is not known)
* @param identifier The name of the variable
* @return A value
*/
public ESValue getValue(String identifier) throws EcmaScriptException {
return theScopeChain.getValue(identifier);
}
/**
* Get the value of a variable in the scope chain (when its hash code is known)
* @param identifier The name of the variable
* @param hash Its hash code (must be exact!)
* @return A value
*/
public ESValue getValue(String identifier,int hash) throws EcmaScriptException {
return theScopeChain.getValue(identifier, hash);
}
/**
* Call a routine referenced by name (in the scope chain)
* @param thisObject the this of the called routine
* @param functionName The name of the function
* @param Its hash code
* @param arguments The argument array
* @exception EmcaScriptException In case of any error during evaluation
* @return the resulting value
*/
public ESValue doIndirectCall(ESObject thisObject, String functionName,int hash, ESValue[] arguments) throws EcmaScriptException {
return theScopeChain.doIndirectCall(this, thisObject, functionName, hash, arguments);
}
/**
* Create variable only if does not already exist (do not overwrite parameters
* and functions of the same name)
* @param name the new variable name
* @param hashCode Its hash code
* @exception EmcaScriptException In case of any error during setting
*/
public void createVariable(String name, int hashCode) throws EcmaScriptException {
if (!currentVariableObject.hasProperty(name, hashCode)) {
ESReference newVar = new ESReference(currentVariableObject, name, hashCode);
newVar.putValue(currentVariableObject, ESUndefined.theUndefined);
}
}
/**
* Put a value in a variable (given as a reference)
* @param leftValue The reference to the variable to modify
* @param rightValue The value to set
* @exception EmcaScriptException In case of any error during evaluation
*/
public void putValue(ESReference leftValue, ESValue rightValue) throws EcmaScriptException {
leftValue.putValue(globalObject, rightValue);
}
/**
* Sub evaluator - evaluate an eval string in a program (not a top level evaluation !)
* @param theSource The string to evaluate
* @return The result of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
public ESValue evaluateEvalString(String theSource) throws EcmaScriptException {
ESValue theValue = ESUndefined.theUndefined;
java.io.StringReader is =
new java.io.StringReader(theSource);
EcmaScript parser = new EcmaScript(is);
ASTProgram programNode = null;
StringEvaluationSource es = new StringEvaluationSource(theSource, null);
try {
// ASTProgram n = parser.Program();
programNode = (ASTProgram)parser.Program();
if (debugParse) {
System.out.println();
System.out.println("Dump parse tree of eval (debugParse true)");
programNode.dump("");
}
} catch (ParseException e) {
if (debugParse) {
System.out.println("[[PARSING ERROR DETECTED: (debugParse true)]]");
System.out.println(e.getMessage());
System.out.println("[[BY ROUTINE:]]");
e.printStackTrace();
System.out.println();
}
throw new EcmaScriptParseException(e, es);
} catch (TokenMgrError e) {
if (debugParse) {
System.out.println("[[LEXICAL ERROR DETECTED: (debugParse true)]]");
System.out.println(e.getMessage());
System.out.println("[[BY ROUTINE:]]");
e.printStackTrace();
System.out.println();
}
throw new EcmaScriptLexicalException(e, es);
}
ESObject savedVariableObject = currentVariableObject;
currentVariableObject = globalObject;
try {
functionDeclarationVisitor.processFunctionDeclarations(programNode, es);
varDeclarationVisitor.processVariableDeclarations(programNode, es);
EcmaScriptEvaluateVisitor evaluationVisitor = new EcmaScriptEvaluateVisitor(this);
theValue = evaluationVisitor.evaluateProgram(programNode, es);
if (theValue==null) theValue = ESUndefined.theUndefined; // null is not a valid result
if (evaluationVisitor.getCompletionCode()!= EcmaScriptEvaluateVisitor.C_NORMAL) {
throw new EcmaScriptException("Unexpected " +
evaluationVisitor.getCompletionCodeString() +
" in eval parameter top level" );
}
} finally {
currentVariableObject = savedVariableObject;
}
return theValue;
}
/**
* Sub evaluator - evaluate a loaded file as program (not a top level evaluation !)
* @param file The file to load
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
public ESValue evaluateLoadFile(File file) throws EcmaScriptException {
ESValue theValue = ESUndefined.theUndefined;
if (!file.isFile()) {
throw new EcmaScriptException("File '" + file.getPath() + "' does not exist or is not a text file");
}
EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
FileReader fr=null;
try {
fr = new FileReader(file);
theValue = evaluate(fr, null, es, false); // no return on main file
if (theValue == null) theValue = ESUndefined.theUndefined;
} catch (IOException e) {
throw new EcmaScriptException("IO Error loading file " + file + ": " + e);
} finally {
if (fr!=null) {
try {
fr.close();
} catch (IOException ignore) {
}
}
}
return theValue;
}
/**
* Sub evaluator - evaluate a module (a file or jar entry loaded via
* the FESI.path) as program (not a top level evaluation !)
* @param moduleName The name of the module to load
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
public ESValue evaluateLoadModule(String moduleName) throws EcmaScriptException {
ESValue theValue = ESUndefined.theUndefined;
if (moduleName == null) throw new EcmaScriptException("Missing file or module name for load");
String path = System.getProperty("FESI.path", null);
if (path == null) path = System.getProperty("java.class.path",null);
// System.out.println("** Try loading via " + path);
ESValue value = ESUndefined.theUndefined;
if (path == null) {
File file = new File(moduleName);
try {
value = evaluateLoadFile(file);
} catch (EcmaScriptParseException e) {
e.setNeverIncomplete();
throw e;
}
}
String lcModuleName = moduleName.toLowerCase();
boolean hasSuffix = lcModuleName.endsWith(".es") ||
lcModuleName.endsWith(".esw") ||
lcModuleName.endsWith(".js");
String separator = System.getProperty("path.separator",";");
StringTokenizer st = new StringTokenizer(path, separator);
while (st.hasMoreTokens()) {
String tryPath = st.nextToken();
value = tryLoad(tryPath, moduleName, hasSuffix);
if (value != null) break; // Found
}
if (value == null) {
// Not found
throw new EcmaScriptException("Module " + moduleName + " not found in " + path);
}
return value;
}
/**
* Try to load in a single path (directory or jar) environment
* (Utility routine to try load of each path entry)
* @param tryPath The path to try
* @param moduleName the name of the module to load
* @param hasSuffix true if the module name has a specified suffix
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
private ESValue tryLoad(String tryPath, String moduleName, boolean hasSuffix) throws EcmaScriptException {
// System.out.println("** tryPath: " + tryPath);
File dir = new File(tryPath);
if (dir.isDirectory()) {
File file;
if (hasSuffix) {
file = new File(dir, moduleName);
} else {
file = new File(dir, moduleName+".es");
if (! file.exists()) {
file = new File(dir, moduleName+".esw");
}
if (! file.exists()) {
file = new File(dir, moduleName+".js");
}
}
if (!file.exists()) return null;
// A File is found, load it
String cp;
try {
cp = file.getCanonicalPath();
} catch (IOException e) {
throw new EcmaScriptException("IO error accessing module " + moduleName +
" in directory " + dir, e);
}
// System.out.println("** File found: " + cp);
return evaluateLoadFile(file);
} else if (dir.isFile()) {
// System.out.println("** Looking in jar/zip: " + dir);
ZipFile zipFile;
try {
String cp = dir.getCanonicalPath();
zipFile = new ZipFile(cp);
} catch (IOException e) {
return null; // Cannot open jar/zip, ignore
}
ZipEntry zipEntry;
if (hasSuffix) {
zipEntry = zipFile.getEntry(moduleName);
} else {
zipEntry = zipFile.getEntry(moduleName + ".es");
if (zipEntry==null) {
zipEntry = zipFile.getEntry(moduleName + ".esw");
}
if (zipEntry==null) {
zipEntry = zipFile.getEntry(moduleName + ".js");
}
}
if (zipEntry == null) return null; // Not found in this jar file
byte buf[] = null;
try {
InputStream inputStream = zipFile.getInputStream(zipEntry);
int limit = (int)zipEntry.getSize();
buf = new byte[limit];
int total = 0;
while (total < limit)
{
int ct = inputStream.read(buf,total,limit-total);
total = total + ct;
if (ct == 0) {
throw new IOException ("Only " +
total + " bytes out of " + limit + " read from entry '" +
moduleName + "' in jar '" + zipFile.getName() +"'");
}
}
inputStream.close();
} catch (IOException e) {
if (ESLoader.isDebugLoader()) System.out.println(" ** Error reading jar: " + e);
return null;
}
EvaluationSource es = new JarEvaluationSource(dir.getPath(), moduleName, null);
Reader r = new StringReader(new String(buf));
ESValue theValue = evaluate(r, null, es, false); // no return on main file
if (theValue == null) theValue = ESUndefined.theUndefined;
return theValue;
}
return null;
}
/**
* subevaluator - Evaluate a function node (inside a program evaluation)
* @param node The AST node representing the list of statements
* @param es The evaluation source information for backtracce
* @param localVariableNames The set of local variable to create
* @param thisObject The this of this evaluation (so to speak)
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
public ESValue evaluateFunction(ASTStatementList node,
EvaluationSource es,
ESObject variableObject,
Vector localVariableNames,
ESObject thisObject) throws EcmaScriptException {
ESValue theValue = ESUndefined.theUndefined;
ESObject savedVariableObject = currentVariableObject;
ESObject savedThisObject = currentThisObject;
ScopeChain previousScopeChain = theScopeChain;
currentVariableObject = variableObject;
currentThisObject = thisObject;
theScopeChain = new ScopeChain(globalObject, null);
theScopeChain = new ScopeChain(variableObject, theScopeChain);
// EvaluationSource savedEvaluationSource = currentEvaluationSource;
// currentEvaluationSource = es;
try {
for (Enumeration e = localVariableNames.elements() ; e.hasMoreElements() ;) {
String variable =(String)(e.nextElement());
createVariable(variable, variable.hashCode());
}
EcmaScriptEvaluateVisitor evaluationVisitor = new EcmaScriptEvaluateVisitor(this);
theValue = evaluationVisitor.evaluateFunction(node, es);
int cc = evaluationVisitor.getCompletionCode();
if ((cc!= EcmaScriptEvaluateVisitor.C_NORMAL) &&
(cc!= EcmaScriptEvaluateVisitor.C_RETURN)) {
throw new EcmaScriptException("Unexpected " +
evaluationVisitor.getCompletionCodeString() +
" in function" );
}
} finally {
currentVariableObject = savedVariableObject;
theScopeChain = previousScopeChain;
currentThisObject = savedThisObject;
// currentEvaluationSource = savedEvaluationSource;
}
return theValue;
}
/**
* Sub evaluator - evaluate a with node (inside a program evaluation)
* @param node The with statement body
* @param scopeObject the new scope for this with
* @param es The evaluation source for back trace
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
public ESValue evaluateWith(ASTStatement node,
ESObject scopeObject,
EvaluationSource es) throws EcmaScriptException {
ESValue theValue = ESUndefined.theUndefined;
theScopeChain = new ScopeChain(scopeObject, theScopeChain);
try {
EcmaScriptEvaluateVisitor evaluationVisitor = new EcmaScriptEvaluateVisitor(this);
theValue = evaluationVisitor.evaluateWith(node, es);
} finally {
theScopeChain = theScopeChain.previousScope();
}
return theValue;
}
/**
* Top level core evaluator (on parsed program),
* Must be called from a function synchronized on the evaluator
* @param program The parsed program information
* @param thisObject The this of the evaluation (usually the global object)
* @param acceptReturn If true accept a return statement in the body
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
public ESValue evaluate(ParsedProgram program,
ESObject thisObject,
boolean acceptReturn) throws EcmaScriptException {
ASTProgram node = program.getProgramNode();
ESValue theValue = ESUndefined.theUndefined;
ESObject savedVariableObject = currentVariableObject;
ESObject savedThisObject = currentThisObject;
ScopeChain previousScopeChain = theScopeChain;
theScopeChain = new ScopeChain(globalObject, null);
currentVariableObject = globalObject;
currentThisObject = (thisObject != null) ? thisObject : globalObject;
EcmaScriptEvaluateVisitor evaluationVisitor = new EcmaScriptEvaluateVisitor(this);
try {
functionDeclarationVisitor.processFunctionDeclarations(node, program.getEvaluationSource(), thisObject);
Vector variables = program.getVariableNames();
for (Enumeration e = variables.elements() ; e.hasMoreElements() ;) {
String variable = (String)(e.nextElement());
createVariable(variable,variable.hashCode());
}
theValue = evaluationVisitor.evaluateProgram(node, program.getEvaluationSource());
} finally {
currentVariableObject = savedVariableObject;
theScopeChain = previousScopeChain;
currentThisObject = savedThisObject;
}
int completionCode = evaluationVisitor.getCompletionCode();
if (completionCode != EcmaScriptEvaluateVisitor.C_NORMAL) {
if (completionCode != EcmaScriptEvaluateVisitor.C_RETURN) {
throw new EcmaScriptException("Unexpected " +
evaluationVisitor.getCompletionCodeString() +
" in main program" );
} else if (!acceptReturn) {
throw new EcmaScriptException(
"Return is not accepted in main program with the 'eval' interface" );
}
}
return theValue;
}
/**
* subevaluator - Evaluate an event function - must be synchronized
* @param sourceObject The source of the event (wrapped)
* @param theFunction The function to call
* @param args The arguments of the event
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public void evaluateEvent(
ESWrapper sourceObject,
ESObject theFunction,
Object [] args) throws EcmaScriptException {
ESValue [] esArgs = new ESValue[args.length];
for (int i=0; i<args.length; i++) {
// esArgs[i] = new ESWrapper(args[i], this);
esArgs[i] = ESLoader.normalizeValue(args[i], this);
}
theFunction.callFunction(sourceObject, esArgs);
}
/**
* Top eval (synchronized) evaluate on identified stream
* @param is Input stream to evaluate
* @param thisObject The this of this evaluation
* @param es the identification of the source for back trace
* @param acceptReturn If true accepts return in main body
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(java.io.Reader is,
ESObject thisObject,
EvaluationSource es,
boolean acceptReturn) throws EcmaScriptException {
ESValue theValue = ESUndefined.theUndefined;
EcmaScript parser = new EcmaScript(is);
ASTProgram programNode = null;
try {
programNode = (ASTProgram) parser.Program();
if (debugParse) {
System.out.println();
System.out.println("@@ Dumping parse tree (debugParse true)");
programNode.dump("");
}
} catch (ParseException e) {
if (debugParse) {
System.out.println("[[PARSING ERROR DETECTED: (debugParse true)]]");
System.out.println(e.getMessage());
System.out.println("[[BY ROUTINE:]]");
e.printStackTrace();
System.out.println();
}
throw new EcmaScriptParseException(e, es);
} catch (TokenMgrError e) {
if (debugParse) {
System.out.println("[[LEXICAL ERROR DETECTED: (debugParse true)]]");
System.out.println(e.getMessage());
System.out.println("[[BY ROUTINE:]]");
e.printStackTrace();
System.out.println();
}
throw new EcmaScriptLexicalException(e, es);
}
Vector variableList = varDeclarationVisitor.processVariableDeclarations(programNode, es);
ParsedProgram program = new ParsedProgram(programNode, variableList, es);
theValue = evaluate(program, thisObject, acceptReturn);
return theValue;
}
/**
* Top eval (synchronized) evaluate on anonymous stream
* @param is Input stream to evaluate
* @param thisObject The this of this evaluation
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(Reader is, ESObject thisObject) throws EcmaScriptException {
EvaluationSource es = new UserEvaluationSource("<Anonymous stream>", null);
return evaluate (is, thisObject, es, false); // no return on anonymous streams
}
/**
* Top eval (synchronized) evaluate on anonymous stream with null thisObject
* @param is Input stream to evaluate
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(Reader is) throws EcmaScriptException {
return evaluate (is, null);
}
/**
* Top eval (synchronized) evaluate on an identified string (used by the GUI)
* @param text source to evaluate
* @param source Identification of the source
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(String text, String source) throws EcmaScriptException {
java.io.StringReader is = null;
ESValue v = null;
EvaluationSource es = new UserEvaluationSource(source, null);
try {
is = new java.io.StringReader(text);
v = evaluate(is, globalObject, es, false);
} finally {
if (is != null) is.close();
}
return v;
}
/**
* Top eval (synchronized) evaluate a file
* @param file file to evaluate
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(File file)
throws EcmaScriptException, IOException {
return evaluate(file, null);
}
/**
* Top eval (synchronized) evaluate a file
* @param file file to evaluate
* @param thisObject The this to use for the evaluation
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(File file, ESObject thisObject)
throws EcmaScriptException, IOException {
EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
FileReader fr = null;
ESValue value = null;
try {
fr = new FileReader(file);
value = evaluate (fr, thisObject, es, false); // No return on a main file
} finally {
if (fr!= null) {
try {
fr.close();
} catch (IOException ignore) {
}
}
}
return value;
}
/**
* Top eval (synchronized) evaluate on an anonymous string
* @param theSource source to evaluate
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(String theSource) throws EcmaScriptException {
return evaluate(theSource, null, false);
}
//synchronized public ESValue evaluate(String theSource, ESObject thisObject) throws EcmaScriptException {
// return evaluate(theSource, thisObject, false); // No return allowed
//}
/**
* Top eval (synchronized) evaluate on an anonymous string with
* thisObject and acceptBoolean
* @param theSource source to evaluate
* @param thisObject this for the evaluation
* @param returnAccepted If true a return is accepted in the main body
* @return The last value of the evaluation
* @exception EmcaScriptException In case of any error during evaluation
*/
synchronized public ESValue evaluate(String theSource,
ESObject thisObject,
boolean returnAccepted)
throws EcmaScriptException {
java.io.StringReader is = null;
ESValue v = null;
EvaluationSource es = new StringEvaluationSource(theSource, null);
try {
is = new java.io.StringReader(theSource);
v = evaluate(is, thisObject, es, returnAccepted);
} finally {
if (is != null) is.close();
}
return v;
}
}