X-Git-Url: http://git.megacz.com/?p=org.ibex.js.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fjs%2FInterpreter.java;h=2b4e8887fb0f31ccef244f8cb3eaf549529ec4e9;hp=e20e6307d0d8107375b1a1ffba03e4ff2fce5791;hb=HEAD;hpb=55be062f7146f8ca2899e1234e4546a0756520ee diff --git a/src/org/ibex/js/Interpreter.java b/src/org/ibex/js/Interpreter.java index e20e630..2b4e888 100644 --- a/src/org/ibex/js/Interpreter.java +++ b/src/org/ibex/js/Interpreter.java @@ -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 @@ -248,10 +248,10 @@ class Interpreter implements ByteCodes, Tokens, Pausable { TrapMarker tm = (TrapMarker) o; JS key = tm.t.key(); JS target = tm.t.target(); - if(tm.t.isWriteTrap() != write) throw new JSExn("tried to do a " + (write?"write":"read") + " cascade in a " + (write?"read":"write") + " trap"); + if(tm.t.isWriteTrap() != write) + throw new JSExn("tried to do a "+(write?"write":"read") + " cascade in a " + (write?"read":"write") + " trap"); JS.Trap t = write ? tm.t.nextWrite() : tm.t.nextRead(); - // FIXME: Doesn't handle multiple levels of clone's (probably can just make this a while loop) - if(t == null && target instanceof JS.Clone) { + while (t == null && target instanceof JS.Clone) { target = ((JS.Clone)target).clonee; t = target.getTrap(key); if(t != null) t = write ? t.write() : t.read(); @@ -344,10 +344,9 @@ class Interpreter implements ByteCodes, Tokens, Pausable { } case CALL: case CALLMETHOD: { - // FIXME: can a lot of simple cases in Parser be - // reduced so creating a new JS[] is not necessary? JS[] jsargs; if (arg instanceof JSNumber.I) { + // FIXME: we should be able to recycle JS[]'s here jsargs = new JS[((JSNumber.I)arg).toInt()]; for (int i=0; i < jsargs.length; i++) jsargs[i] = (JS)stack.pop(); } else jsargs = (JS[])arg; @@ -372,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; @@ -390,35 +389,12 @@ class Interpreter implements ByteCodes, Tokens, Pausable { case THROW: throw new JSExn((JS)stack.pop(), this); - /* FIXME GRAMMAR - case MAKE_GRAMMAR: { - final Grammar r = (Grammar)arg; - final JSScope final_scope = scope; - Grammar r2 = new Grammar() { - public int match(String s, int start, Map v, JSScope scope) throws JSExn { - return r.match(s, start, v, final_scope); - } - public int matchAndWrite(String s, int start, Map v, JSScope scope, String key) throws JSExn { - return r.matchAndWrite(s, start, v, final_scope, key); - } - public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn { - Map v = new Map(); - r.matchAndWrite((String)a0, 0, v, final_scope, "foo"); - return v.get("foo"); - } - }; - Object obj = stack.pop(); - if (obj != null && obj instanceof Grammar) r2 = new Grammar.Alternative((Grammar)obj, r2); - stack.push(r2); - break; - } - */ case ADD_TRAP: case DEL_TRAP: { JS val = (JS)stack.pop(); JS key = (JS)stack.pop(); JS js = (JS)stack.peek(); // A trap addition/removal - if(!(val instanceof JSFunction)) throw new JSExn("tried to add/remove a non-function trap"); // FIXME + if(!(val instanceof JSFunction)) throw new JSExn("tried to add/remove a non-function trap"); if(op == ADD_TRAP) js.addTrap(key, val); else js.delTrap(key, val); break; @@ -492,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: { @@ -558,7 +541,7 @@ class Interpreter implements ByteCodes, Tokens, Pausable { void setupTrap(JS.Trap t, JS val, CallMarker cm) throws JSExn { stack.push(cm); stack.push(new TrapArgs(t, val)); - f = (JSFunction)t.function(); // FIXME + f = (JSFunction)t.function(); scope = f.parentScope; pc = 0; } @@ -634,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);