diff --git a/js/js2/java/BinaryNode.java b/js/js2/java/BinaryNode.java index c11e11b8d613..2ef4739b9b8a 100644 --- a/js/js2/java/BinaryNode.java +++ b/js/js2/java/BinaryNode.java @@ -29,6 +29,12 @@ class BinaryNode extends ExpressionNode { if (op == ".") return lV.getProp(theEnv, rV.toJSString(theEnv)); + else + if (op == "()") + return lV.call(theEnv, rV); + else + if (op == ",") + return JSValueList.buildList(lV, rV); else { System.out.println("missing binary op " + op); return null; diff --git a/js/js2/java/ControlNode.java b/js/js2/java/ControlNode.java index 8503f5c7b590..fbe217e61c8f 100644 --- a/js/js2/java/ControlNode.java +++ b/js/js2/java/ControlNode.java @@ -33,7 +33,7 @@ class ControlNode { ControlNode eval(Environment theEnv) { - if (expr != null) expr.eval(theEnv); + if (expr != null) theEnv.resultValue = expr.eval(theEnv); return next; } diff --git a/js/js2/java/Environment.java b/js/js2/java/Environment.java index bd4ce6d68002..006320df63ab 100644 --- a/js/js2/java/Environment.java +++ b/js/js2/java/Environment.java @@ -12,5 +12,6 @@ class Environment { return result.toString(); } + JSValue resultValue; } \ No newline at end of file diff --git a/js/js2/java/FunctionNode.java b/js/js2/java/FunctionNode.java new file mode 100644 index 000000000000..75dc34a1f124 --- /dev/null +++ b/js/js2/java/FunctionNode.java @@ -0,0 +1,18 @@ +class FunctionNode extends ExpressionNode { + + FunctionNode(JSIdentifier aName, ControlNodeGroup aBody) + { + fn = new NativeFunction(aBody.getHead()); + name = aName; + } + + JSValue eval(Environment theEnv) + { + theEnv.scope.putProp(theEnv, name, fn); + return fn; + } + + JSString name; + NativeFunction fn; + +} \ No newline at end of file diff --git a/js/js2/java/JSGrammar.g b/js/js2/java/JSGrammar.g index 73a4b3cdf79d..4a0f2594bccb 100644 --- a/js/js2/java/JSGrammar.g +++ b/js/js2/java/JSGrammar.g @@ -387,7 +387,7 @@ type_expression[boolean initial, boolean allowIn] // ********* Statements ********** statement[int scope, boolean non_empty, ControlNodeGroup container] - : (definition[scope]) => definition[scope] + : (definition[scope, container]) => definition[scope, container] | code_statement[non_empty, container, null] ; @@ -692,28 +692,29 @@ import_source ; // ********* Definitions ********** -definition[int scope] - : visibility global_definition - | local_definition[scope] +definition[int scope, ControlNodeGroup container] + : visibility global_definition[container] + | local_definition[scope, container] ; -global_definition +global_definition[ControlNodeGroup container] { ExpressionNode e = null; } : version_definition semicolon | variable_definition semicolon // Syntactic predicate is required to disambiguate between getter/setter methods // and getter/setter functions - | ("traditional" | "function" | (("getter" | "setter") "function")) => e = function_definition + | ("traditional" | "function" | (("getter" | "setter") "function")) + => e = function_definition { container.add(new ControlNode(e)); } | member_definition | class_definition ; -local_definition[int scope] +local_definition[int scope, ControlNodeGroup container] { ExpressionNode e = null; } : {scope == TopLevelScope || scope == ClassScope}? (class_definition | member_definition) | variable_definition semicolon - | e = function_definition + | e = function_definition { container.add(new ControlNode(e)); } ; // ********* Visibility Specifications ********** @@ -780,7 +781,7 @@ function_definition returns [ExpressionNode e] : e = named_function | "getter" e = named_function | "setter" e = named_function - | traditional_function + | e = traditional_function ; anonymous_function returns [ExpressionNode e] @@ -838,9 +839,10 @@ result_signature )? ; -traditional_function - { ExpressionNode e = null; ControlNodeGroup c = new ControlNodeGroup(); } - : "traditional" "function" e = identifier "(" traditional_parameter_list ")" block[BlockScope, c] +traditional_function returns [ExpressionNode e] + { e = null; JSIdentifier id = null; ControlNodeGroup c = new ControlNodeGroup(); } + : "traditional" "function" id = identifier "(" traditional_parameter_list ")" block[BlockScope, c] + { e = new FunctionNode(id, c); } ; traditional_parameter_list diff --git a/js/js2/java/JSValue.java b/js/js2/java/JSValue.java index cab31fcc64dd..3bcf454d6656 100644 --- a/js/js2/java/JSValue.java +++ b/js/js2/java/JSValue.java @@ -151,6 +151,10 @@ class JSValue extends ExpressionNode { return toJSObject(theEnv).putProp(theEnv, id, rV); } + JSValue call(Environment theEnv, JSValue rV) { + throw new JSException(new JSString("[[call]] not implemented")); + } + JSValue defaultValue(Environment theEnv, String hint) { /* When the [[DefaultValue]] method of O is called with hint String, the following steps are taken: diff --git a/js/js2/java/JSValueList.java b/js/js2/java/JSValueList.java new file mode 100644 index 000000000000..c9e522c0f615 --- /dev/null +++ b/js/js2/java/JSValueList.java @@ -0,0 +1,40 @@ + +import java.util.Vector; + +class JSValueList extends JSValue { + + static JSValueList buildList(JSValue left, JSValue right) + { + JSValueList theList; + if (left instanceof JSValueList) { + theList = (JSValueList)left; + theList.add(right); + } + else + if (right instanceof JSValueList) { + theList = (JSValueList)right; + theList.add(left); + } + else { + theList = new JSValueList(); + theList.add(left); + theList.add(right); + } + + return theList; + } + + void add(JSValue v) + { + if (v instanceof JSValueList) { + JSValueList vl = (JSValueList)v; + for (int i = 0; i < vl.contents.size(); i++) + contents.addElement((JSValue)(vl.contents.elementAt(i))); + } + else + contents.addElement(v); + } + + Vector contents = new Vector(); + +} \ No newline at end of file diff --git a/js/js2/java/NativeFunction.java b/js/js2/java/NativeFunction.java new file mode 100644 index 000000000000..6e838be01cf3 --- /dev/null +++ b/js/js2/java/NativeFunction.java @@ -0,0 +1,20 @@ +class NativeFunction extends JSObject { + + NativeFunction(ControlNode aBody) + { + super("Function"); + body = aBody; + } + + JSValue call(Environment theEnv, JSValue rV) + { + ControlNode c = body; + while (c != null) c = c.eval(theEnv); + + return theEnv.resultValue; + } + + + ControlNode body; + +} \ No newline at end of file