fix nasty bug in numerical comparison in Interpreter
[org.ibex.js.git] / src / org / ibex / js / Interpreter.java
index 77da0ab..2b4e888 100644 (file)
@@ -71,7 +71,7 @@ class Interpreter implements ByteCodes, Tokens, Pausable {
         pausecount++;
         switch(f.op[pc]) {
             case Tokens.RETURN: case ByteCodes.PUT: get = false; break;
-            case ByteCodes.GET: case ByteCodes.CALL: get = true; break;
+            case ByteCodes.GET: case ByteCodes.GET_PRESERVE: case ByteCodes.CALLMETHOD: case ByteCodes.CALL: get = true; break;
             default: throw new Error("paused on unexpected bytecode: " + f.op[pc]);
         }
     }
@@ -159,7 +159,7 @@ class Interpreter implements ByteCodes, Tokens, Pausable {
             case BREAK:
             case CONTINUE:
                 while(!stack.empty()) {
-                    JS o = (JS)stack.pop();
+                    Object o = stack.pop();
                     if (o instanceof CallMarker) je("break or continue not within a loop");
                     if (o instanceof TryMarker) {
                         if(((TryMarker)o).finallyLoc < 0) continue; // no finally block, keep going
@@ -371,8 +371,8 @@ class Interpreter implements ByteCodes, Tokens, Pausable {
 
                 if (object instanceof JSFunction) {
                     stack.push(new CallMarker(this));
-                    stack.push(jsargs);
                     f = (JSFunction)object;
+                    stack.push(new JSArgs(jsargs, f));
                     scope = f.parentScope;
                     pc = -1;
                     break;
@@ -468,14 +468,21 @@ class Interpreter implements ByteCodes, Tokens, Pausable {
                 case RSH: stack.push(JSU.N(JSU.toLong(left) >> JSU.toLong(right))); break;
                 case URSH: stack.push(JSU.N(JSU.toLong(left) >>> JSU.toLong(right))); break;
                         
-                //#repeat </<=/>/>= LT/LE/GT/GE
-                case LT: {
+                case LT: case LE: case GT: case GE: {
+                    int cmp = 0;
                     if(left instanceof JSString && right instanceof JSString)
-                        stack.push(JSU.B(JSU.toString(left).compareTo(JSU.toString(right)) < 0));
+                        cmp = JSU.toString(left).compareTo(JSU.toString(right));
                     else
-                        stack.push(JSU.B(JSU.toDouble(left) < JSU.toDouble(right)));
+                        cmp = (int)(100 * (JSU.toDouble(left) - JSU.toDouble(right)));
+                    switch(op) {
+                        case LE: stack.push(JSU.B(cmp <= 0)); break;
+                        case LT: stack.push(JSU.B(cmp <  0)); break;
+                        case GE: stack.push(JSU.B(cmp >= 0)); break;
+                        case GT: stack.push(JSU.B(cmp >  0)); break;
+                        default: throw new RuntimeException("impossible");
+                    }
+                    break;
                 }
-                //#end
                     
                 case EQ:
                 case NE: {
@@ -610,7 +617,10 @@ class Interpreter implements ByteCodes, Tokens, Pausable {
         public JSArgs(JS[] args, JS callee) { this.args = args; this.callee = callee; }
         
         public JS get(JS key) throws JSExn {
-            if(JSU.isInt(key)) return args[JSU.toInt(key)];
+            if(JSU.isInt(key)) {
+                int i = JSU.toInt(key);
+                return i>=args.length ? null : args[i];
+            }
             //#switch(JSU.toString(key))
             case "callee": return callee;
             case "length": return JSU.N(args.length);