diff --git a/mozilla/js/js2/java/ArithmeticNode.java b/mozilla/js/js2/java/ArithmeticNode.java index 7afacfc4bff..f6d4736349c 100644 --- a/mozilla/js/js2/java/ArithmeticNode.java +++ b/mozilla/js/js2/java/ArithmeticNode.java @@ -7,23 +7,24 @@ class ArithmeticNode extends BinaryNode { void eval(Environment theEnv) { - super.eval(theEnv); - double dR = theEnv.theStack.pop().d; - double dL = theEnv.theStack.pop().d; + left.eval(theEnv); + JSValue lV = theEnv.theStack.pop(); + right.eval(theEnv); + if (op == "+") - theEnv.theStack.push(new StackValue(dL + dR)); + lV.add(theEnv); else if (op == "-") - theEnv.theStack.push(new StackValue(dL - dR)); + lV.subtract(theEnv); else if (op == "*") - theEnv.theStack.push(new StackValue(dL * dR)); + lV.multiply(theEnv); else if (op == "/") - theEnv.theStack.push(new StackValue(dL / dR)); + lV.divide(theEnv); else if (op == "%") - theEnv.theStack.push(new StackValue(dL % dR)); + lV.remainder(theEnv); else System.out.println("missing arithmetic op " + op); } diff --git a/mozilla/js/js2/java/AssignmentNode.java b/mozilla/js/js2/java/AssignmentNode.java index 1df0a4160d4..e65f66f2287 100644 --- a/mozilla/js/js2/java/AssignmentNode.java +++ b/mozilla/js/js2/java/AssignmentNode.java @@ -10,10 +10,10 @@ class AssignmentNode extends BinaryNode { left.evalLHS(theEnv); right.eval(theEnv); - double dValue = theEnv.theStack.pop().d; - String id = theEnv.theStack.pop().id; + JSValue rValue = theEnv.theStack.pop(); + JSValue lValue = theEnv.theStack.pop(); - theEnv.theGlobals.put(id, new Double(dValue)); + theEnv.theGlobals.put(lValue.toString(), rValue); } diff --git a/mozilla/js/js2/java/BitwiseNode.java b/mozilla/js/js2/java/BitwiseNode.java index 3e760658a3b..9d8b816dc8a 100644 --- a/mozilla/js/js2/java/BitwiseNode.java +++ b/mozilla/js/js2/java/BitwiseNode.java @@ -7,26 +7,27 @@ class BitwiseNode extends BinaryNode { void eval(Environment theEnv) { - super.eval(theEnv); - int iR = (int)(theEnv.theStack.pop().d); - int iL = (int)(theEnv.theStack.pop().d); + left.eval(theEnv); + JSInteger lV = theEnv.theStack.pop().toJSInteger(); + right.eval(theEnv); + if (op == "&") - theEnv.theStack.push(new StackValue(iL & iR)); + lV.and(theEnv); else if (op == "|") - theEnv.theStack.push(new StackValue(iL | iR)); + lV.or(theEnv); else if (op == "^") - theEnv.theStack.push(new StackValue(iL ^ iR)); + lV.xor(theEnv); else if (op == "<<") - theEnv.theStack.push(new StackValue(iL << iR)); + lV.shr(theEnv); else if (op == ">>") - theEnv.theStack.push(new StackValue(iL >> iR)); + lV.shl(theEnv); else if (op == ">>>") - theEnv.theStack.push(new StackValue(iL >>> iR)); + lV.ushl(theEnv); else System.out.println("missing bitwise op " + op); } diff --git a/mozilla/js/js2/java/ConditionalNode.java b/mozilla/js/js2/java/ConditionalNode.java index d55a00e53d0..1d317438b6f 100644 --- a/mozilla/js/js2/java/ConditionalNode.java +++ b/mozilla/js/js2/java/ConditionalNode.java @@ -27,8 +27,8 @@ class ConditionalNode extends ControlNode { ControlNode eval(Environment theEnv) { ControlNode n = super.eval(theEnv); - double d = theEnv.theStack.pop().d; - if (d != 0.0) + JSBoolean b = theEnv.theStack.pop().toJSBoolean(); + if (b.isTrue()) return trueCode; else return n; diff --git a/mozilla/js/js2/java/JSBoolean.java b/mozilla/js/js2/java/JSBoolean.java index 40f12200c91..49a48afe418 100644 --- a/mozilla/js/js2/java/JSBoolean.java +++ b/mozilla/js/js2/java/JSBoolean.java @@ -1,21 +1,33 @@ class JSBoolean extends JSValue { - - JSBoolean(String s) + + static JSBoolean JSTrue = new JSBoolean(true); + static JSBoolean JSFalse = new JSBoolean(false); + + private JSBoolean(boolean p) { - if (s.equals("true")) - b = true; - else - if (s.equals("false")) - b = false; - else - throw new RuntimeException("Bad string for JSBoolean constructor : " + s); + b = p; } void eval(Environment theEnv) { - theEnv.theStack.push(new StackValue(b ? 1 : 0)); + theEnv.theStack.push(this); } + boolean isTrue() + { + return b; + } + + boolean isFalse() + { + return !b; + } + + JSBoolean toJSBoolean() { + return this; + } + + boolean b; } \ No newline at end of file diff --git a/mozilla/js/js2/java/JSDouble.java b/mozilla/js/js2/java/JSDouble.java index 630f0473925..914ba27d3e0 100644 --- a/mozilla/js/js2/java/JSDouble.java +++ b/mozilla/js/js2/java/JSDouble.java @@ -1,5 +1,10 @@ class JSDouble extends JSNumber { + JSDouble(double p) + { + d = p; + } + JSDouble(String s) { d = new Double(s).doubleValue(); @@ -12,7 +17,88 @@ class JSDouble extends JSNumber { void eval(Environment theEnv) { - theEnv.theStack.push(new StackValue(d)); + theEnv.theStack.push(this); + } + + + void add(Environment theEnv) { + JSValue vR = theEnv.theStack.peek(); + if (vR instanceof JSString) + toJSString().add(theEnv); + else { + theEnv.theStack.pop(); + theEnv.theStack.push(new JSDouble(d + vR.toJSDouble().d)); + } + } + + void subtract(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSDouble(d - vR.toJSDouble().d)); + } + + void multiply(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSDouble(d * vR.toJSDouble().d)); + } + + void divide(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSDouble(d / vR.toJSDouble().d)); + } + + void remainder(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSDouble(d % vR.toJSDouble().d)); + } + + void gt(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push((d > vR.toJSDouble().d) ? JSBoolean.JSTrue : JSBoolean.JSFalse); + } + + void ge(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push((d >= vR.toJSDouble().d) ? JSBoolean.JSTrue : JSBoolean.JSFalse); + } + + void lt(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push((d < vR.toJSDouble().d) ? JSBoolean.JSTrue : JSBoolean.JSFalse); + } + + void le(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push((d <= vR.toJSDouble().d) ? JSBoolean.JSTrue : JSBoolean.JSFalse); + } + + void eq(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push((d == vR.toJSDouble().d) ? JSBoolean.JSTrue : JSBoolean.JSFalse); + } + + void ne(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push((d != vR.toJSDouble().d) ? JSBoolean.JSTrue : JSBoolean.JSFalse); + } + + JSDouble toJSDouble() { + return this; + } + + JSInteger toJSInteger() { + return new JSInteger((int)d); + } + + JSBoolean toJSBoolean() { + return (d != 0.0) ? JSBoolean.JSTrue : JSBoolean.JSFalse; + } + + JSString toJSString() { + return new JSString(Double.toString(d)); + } + + public String toString() { + return Double.toString(d); } double d; diff --git a/mozilla/js/js2/java/JSException.java b/mozilla/js/js2/java/JSException.java index 8144ae293c4..fe06f64f129 100644 --- a/mozilla/js/js2/java/JSException.java +++ b/mozilla/js/js2/java/JSException.java @@ -2,16 +2,16 @@ class JSException extends RuntimeException { - JSException(StackValue x) + JSException(JSValue x) { value = x; } - StackValue getValue() + JSValue getValue() { return value; } - StackValue value; + JSValue value; } \ No newline at end of file diff --git a/mozilla/js/js2/java/JSGrammar.g b/mozilla/js/js2/java/JSGrammar.g index fc46889ce54..a48726cb042 100644 --- a/mozilla/js/js2/java/JSGrammar.g +++ b/mozilla/js/js2/java/JSGrammar.g @@ -45,14 +45,14 @@ options { // ********* Identifiers ********** identifier returns [ExpressionNode e] { e = null; } - : opI:IDENT { e = new JSObject("object", opI.getText()); } - | "version" { e = new JSObject("object", "version"); } - | "override" { e = new JSObject("object", "override"); } - | "method" { e = new JSObject("object", "method"); } - | "getter" { e = new JSObject("object", "getter"); } - | "setter" { e = new JSObject("object", "setter"); } - | "traditional" { e = new JSObject("object", "traditional"); } - | "constructor" { e = new JSObject("object", "constructor"); } + : opI:IDENT { e = new JSObject(opI.getText()); } + | "version" { e = new JSObject("version"); } + | "override" { e = new JSObject("override"); } + | "method" { e = new JSObject("method"); } + | "getter" { e = new JSObject("getter"); } + | "setter" { e = new JSObject("setter"); } + | "traditional" { e = new JSObject("traditional"); } + | "constructor" { e = new JSObject("constructor"); } ; qualified_identifier returns [ExpressionNode e] @@ -79,15 +79,15 @@ primary_expression[boolean initial] returns [ExpressionNode e] simple_expression returns [ExpressionNode e] { e = null; } - : "null" { e = new JSObject("object", "null"); } - | "true" { e = new JSBoolean("true"); } - | "false" { e = new JSBoolean("false"); } + : "null" { e = new JSObject("null"); } + | "true" { e = JSBoolean.JSTrue; } + | "false" { e = JSBoolean.JSFalse; } | opN:NUMBER { e = new JSDouble(opN.getText()); } | opS:STRING { e = new JSString(opS.getText()); } - | "this" { e = new JSObject("object", "this"); } - | "super" { e = new JSObject("object", "super"); } + | "this" { e = new JSObject("this"); } + | "super" { e = new JSObject("super"); } | e = qualified_identifier_or_parenthesized_expression - | opR:REGEXP { e = new JSObject("regexp", opR.getText()); } + | opR:REGEXP { e = new JSObject(opR.getText()); } | e = array_literal ; diff --git a/mozilla/js/js2/java/JSInteger.java b/mozilla/js/js2/java/JSInteger.java index fea88f3d51d..9d35e0b4352 100644 --- a/mozilla/js/js2/java/JSInteger.java +++ b/mozilla/js/js2/java/JSInteger.java @@ -5,11 +5,62 @@ class JSInteger extends JSNumber { i = new Integer(s).intValue(); } - void eval(Environment theEnv) + JSInteger(int p) { - theEnv.theStack.push(new StackValue(i)); + i = p; } + void eval(Environment theEnv) + { + theEnv.theStack.push(this); + } + + JSBoolean toJSBoolean() { + return (i != 0) ? JSBoolean.JSTrue : JSBoolean.JSFalse; + } + + JSDouble toJSDouble() { + return new JSDouble(i); + } + + JSInteger toJSInteger() { + return this; + } + + JSString toJSString() { + return new JSString(Integer.toString(i)); + } + + void and(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSInteger(i & vR.toJSInteger().i)); + } + + void or(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSInteger(i | vR.toJSInteger().i)); + } + + void xor(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSInteger(i ^ vR.toJSInteger().i)); + } + + void shl(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSInteger(i >> vR.toJSInteger().i)); + } + + void shr(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSInteger(i << vR.toJSInteger().i)); + } + + void ushl(Environment theEnv) { + JSValue vR = theEnv.theStack.pop(); + theEnv.theStack.push(new JSInteger(i >>> vR.toJSInteger().i)); + } + int i; } \ No newline at end of file diff --git a/mozilla/js/js2/java/JSNumber.java b/mozilla/js/js2/java/JSNumber.java index 02651d3f377..d8d7b7b216d 100644 --- a/mozilla/js/js2/java/JSNumber.java +++ b/mozilla/js/js2/java/JSNumber.java @@ -1,3 +1,3 @@ -class JSNumber extends JSValue { +abstract class JSNumber extends JSValue { } \ No newline at end of file diff --git a/mozilla/js/js2/java/JSObject.java b/mozilla/js/js2/java/JSObject.java index 8d6019950ce..0adeb7ac8d8 100644 --- a/mozilla/js/js2/java/JSObject.java +++ b/mozilla/js/js2/java/JSObject.java @@ -1,40 +1,38 @@ class JSObject extends JSValue { - JSObject(String aType, String aValue) + static JSObject JSUndefined = new JSObject("undefined"); + + JSObject(String aValue) { - type = aType; value = aValue; } String print(String indent) { - return indent + "JSObject " + type + " : " + value + "\n"; + return indent + "JSObject : " + value + "\n"; } void evalLHS(Environment theEnv) { - if (type == "object") { - theEnv.theStack.push(new StackValue(value)); - } - else { - System.out.println("EvalLHS on non-object"); - } + theEnv.theStack.push(this); } void eval(Environment theEnv) { - if (type.equals("object")) { - Double d = (Double)(theEnv.theGlobals.get(value)); - if (d == null) { - System.out.println("Accessed undefined : " + value); - theEnv.theStack.push(new StackValue(0.0)); - } - else - theEnv.theStack.push(new StackValue(d.doubleValue())); + JSValue v = (JSValue)(theEnv.theGlobals.get(value)); + if (v == null) { + System.out.println("Accessed undefined : " + value); + theEnv.theStack.push(JSUndefined); } + else + theEnv.theStack.push(v); } - - String type; + + public String toString() + { + return value; + } + String value; } \ No newline at end of file diff --git a/mozilla/js/js2/java/JSStack.java b/mozilla/js/js2/java/JSStack.java index 7b964ad4e66..0cd4a369552 100644 --- a/mozilla/js/js2/java/JSStack.java +++ b/mozilla/js/js2/java/JSStack.java @@ -5,7 +5,7 @@ class JSStack { Stack stack = new Stack(); - void push(StackValue v) + void push(JSValue v) { stack.push(v); } @@ -15,9 +15,14 @@ class JSStack { return stack.isEmpty(); } - StackValue pop() + JSValue pop() { - return (StackValue)stack.pop(); + return (JSValue)stack.pop(); + } + + JSValue peek() + { + return (JSValue)stack.peek(); } int size() diff --git a/mozilla/js/js2/java/JSString.java b/mozilla/js/js2/java/JSString.java index f1757c5871e..a1e841f8dee 100644 --- a/mozilla/js/js2/java/JSString.java +++ b/mozilla/js/js2/java/JSString.java @@ -7,9 +7,19 @@ class JSString extends JSValue { void eval(Environment theEnv) { - theEnv.theStack.push(new StackValue(s)); + theEnv.theStack.push(this); } + void add(Environment theEnv) + { + JSString vR = theEnv.theStack.pop().toJSString(); + theEnv.theStack.push(new JSString(s + vR.s)); + } + + JSString toJSString() + { + return this; + } String s; diff --git a/mozilla/js/js2/java/JSValue.java b/mozilla/js/js2/java/JSValue.java index 292a6baa9f8..94f4f84ff77 100644 --- a/mozilla/js/js2/java/JSValue.java +++ b/mozilla/js/js2/java/JSValue.java @@ -13,7 +13,38 @@ class JSValue extends ExpressionNode { void eval(Environment theEnv) { throw new RuntimeException("Eval on JSValue"); + } + + void unimplemented(String op) + { + throw new RuntimeException("unimplemented " + op + " called"); } + + void add(Environment theEnv) { unimplemented("add"); } + void subtract(Environment theEnv) { unimplemented("subtract"); } + void multiply(Environment theEnv) { unimplemented("multiply"); } + void divide(Environment theEnv) { unimplemented("divide"); } + void remainder(Environment theEnv) { unimplemented("remainder"); } + void and(Environment theEnv) { unimplemented("and"); } + void or(Environment theEnv) { unimplemented("or"); } + void xor(Environment theEnv) { unimplemented("xor"); } + void shl(Environment theEnv) { unimplemented("shl"); } + void shr(Environment theEnv) { unimplemented("shr"); } + void ushl(Environment theEnv) { unimplemented("ushl"); } + + void gt(Environment theEnv) { unimplemented("gt"); } + void ge(Environment theEnv) { unimplemented("ge"); } + void lt(Environment theEnv) { unimplemented("lt"); } + void le(Environment theEnv) { unimplemented("le"); } + void eq(Environment theEnv) { unimplemented("eq"); } + void ne(Environment theEnv) { unimplemented("ne"); } + + + JSDouble toJSDouble() { unimplemented("toJSDouble"); return null; } + JSInteger toJSInteger() { unimplemented("toJSInteger"); return null; } + JSString toJSString() { unimplemented("toJSString"); return null; } + JSBoolean toJSBoolean() { unimplemented("toJSBoolean"); return null; } + } \ No newline at end of file diff --git a/mozilla/js/js2/java/LogicalNode.java b/mozilla/js/js2/java/LogicalNode.java index a1ce897eeb7..ef2236112f4 100644 --- a/mozilla/js/js2/java/LogicalNode.java +++ b/mozilla/js/js2/java/LogicalNode.java @@ -8,29 +8,29 @@ class LogicalNode extends BinaryNode { void eval(Environment theEnv) { left.eval(theEnv); - double d = theEnv.theStack.pop().d; + JSBoolean b = theEnv.theStack.pop().toJSBoolean(); if (op == "&&") { - if (d == 0.0) - theEnv.theStack.push(new StackValue(0)); + if (b.isFalse()) + theEnv.theStack.push(b); else { right.eval(theEnv); - d = theEnv.theStack.pop().d; - if (d == 0.0) - theEnv.theStack.push(new StackValue(0)); + b = theEnv.theStack.pop().toJSBoolean(); + if (b.isFalse()) + theEnv.theStack.push(b); else - theEnv.theStack.push(new StackValue(1)); + theEnv.theStack.push(JSBoolean.JSTrue); } } if (op == "||") { - if (d != 0.0) - theEnv.theStack.push(new StackValue(1)); + if (b.isTrue()) + theEnv.theStack.push(b); else { right.eval(theEnv); - d = theEnv.theStack.pop().d; - if (d != 0.0) - theEnv.theStack.push(new StackValue(1)); + b = theEnv.theStack.pop().toJSBoolean(); + if (b.isTrue()) + theEnv.theStack.push(b); else - theEnv.theStack.push(new StackValue(0)); + theEnv.theStack.push(JSBoolean.JSFalse); } } else diff --git a/mozilla/js/js2/java/RelationalNode.java b/mozilla/js/js2/java/RelationalNode.java index 460d5927886..2b859532d7f 100644 --- a/mozilla/js/js2/java/RelationalNode.java +++ b/mozilla/js/js2/java/RelationalNode.java @@ -7,26 +7,27 @@ class RelationalNode extends BinaryNode { void eval(Environment theEnv) { - super.eval(theEnv); - double dR = theEnv.theStack.pop().d; - double dL = theEnv.theStack.pop().d; + left.eval(theEnv); + JSValue lV = theEnv.theStack.pop(); + right.eval(theEnv); + if (op == ">") - theEnv.theStack.push(new StackValue((dL > dR) ? 1 : 0)); + lV.gt(theEnv); else if (op == ">=") - theEnv.theStack.push(new StackValue((dL >= dR) ? 1 : 0)); + lV.ge(theEnv); else if (op == "<") - theEnv.theStack.push(new StackValue((dL < dR) ? 1 : 0)); + lV.lt(theEnv); else if (op == "<=") - theEnv.theStack.push(new StackValue((dL <= dR) ? 1 : 0)); + lV.le(theEnv); else if (op == "==") - theEnv.theStack.push(new StackValue((dL == dR) ? 1 : 0)); + lV.eq(theEnv); else if (op == "!=") - theEnv.theStack.push(new StackValue((dL != dR) ? 1 : 0)); + lV.ne(theEnv); else System.out.println("missing relational op"); } diff --git a/mozilla/js/js2/java/StackValue.java b/mozilla/js/js2/java/StackValue.java deleted file mode 100644 index 2245012cde3..00000000000 --- a/mozilla/js/js2/java/StackValue.java +++ /dev/null @@ -1,23 +0,0 @@ -class StackValue { - - StackValue(double x) - { - d = x; - id = ""; - } - - StackValue(String x) - { - id = x; - d = 0; - } - - public String toString() - { - return "StackValue, id = " + id + ", d = " + d; - } - - double d; - String id; - -} \ No newline at end of file diff --git a/mozilla/js/js2/java/SwitchNode.java b/mozilla/js/js2/java/SwitchNode.java index 6803e5338ba..c4b01ab1196 100644 --- a/mozilla/js/js2/java/SwitchNode.java +++ b/mozilla/js/js2/java/SwitchNode.java @@ -22,13 +22,13 @@ class SwitchNode extends ControlNode { ControlNode eval(Environment theEnv) { ControlNode n = super.eval(theEnv); - double d = theEnv.theStack.pop().d; + JSValue v = theEnv.theStack.pop(); int count = caseExpr.size(); for (int i = 0; i < count; i++) { ExpressionNode e = (ExpressionNode)(caseExpr.elementAt(i)); e.eval(theEnv); - double d2 = theEnv.theStack.pop().d; - if (d == d2) + v.eq(theEnv); + if (theEnv.theStack.pop().toJSBoolean().isTrue()) return (ControlNode)(caseCode.elementAt(i)); } if (defaultCode != null) diff --git a/mozilla/js/js2/java/TryNode.java b/mozilla/js/js2/java/TryNode.java index 063d6f00c20..a696451d6b6 100644 --- a/mozilla/js/js2/java/TryNode.java +++ b/mozilla/js/js2/java/TryNode.java @@ -33,7 +33,7 @@ class TryNode extends ControlNode { ExpressionNode e = (ExpressionNode)(catchExpr.elementAt(i)); String id = ((JSObject)e).value; theEnv.theStack.setStack(stackHeight); - theEnv.theGlobals.put(id, new Double(x.getValue().d)); + theEnv.theGlobals.put(id, x.getValue()); return (ControlNode)(catchCode.elementAt(i)); } }