X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fjs%2FInterpreter.java;h=a471412f6a1916014d5a6d1ba46396bb59fc6ec4;hb=6261c41b2ac9d182d8c3541e8e0e5fd00062fa43;hp=66931fdaee4c26e2c27cbfeee35d88e613deccd8;hpb=a060cc5025b58e8d3e319aefa6ae44fe7c6182ad;p=org.ibex.core.git diff --git a/src/org/xwt/js/Interpreter.java b/src/org/xwt/js/Interpreter.java index 66931fd..a471412 100644 --- a/src/org/xwt/js/Interpreter.java +++ b/src/org/xwt/js/Interpreter.java @@ -83,7 +83,7 @@ class Interpreter implements ByteCodes, Tokens { case DUP: stack.push(stack.peek()); break; case NEWSCOPE: scope = new JSScope(scope); break; case OLDSCOPE: scope = scope.getParentScope(); break; - case ASSERT: if (!JS.toBoolean(stack.pop())) throw je("assertion failed"); break; + case ASSERT: if (!JS.toBoolean(stack.pop())) throw je("xwt.assertion.failed" /*FEATURE: line number*/); break; case BITNOT: stack.push(JS.N(~JS.toLong(stack.pop()))); break; case BANG: stack.push(JS.B(!JS.toBoolean(stack.pop()))); break; case NEWFUNCTION: stack.push(((JSFunction)arg).cloneWithNewParentScope(scope)); break; @@ -160,8 +160,9 @@ class Interpreter implements ByteCodes, Tokens { pc = ((TryMarker)o).finallyLoc - 1; continue OUTER; } else if (o instanceof CallMarker) { - if (scope instanceof Trap.TrapScope) { + if (scope instanceof Trap.TrapScope) { // handles return component of a read trap Trap.TrapScope ts = (Trap.TrapScope)scope; + if (retval != null) ts.cascadeHappened = true; if (!ts.cascadeHappened) { ts.cascadeHappened = true; Trap t = ts.t.next; @@ -177,7 +178,7 @@ class Interpreter implements ByteCodes, Tokens { f = t.f; scope = new Trap.TrapScope(f.parentScope, t, ts.val); pc = -1; - break; + continue OUTER; } } } @@ -201,22 +202,36 @@ class Interpreter implements ByteCodes, Tokens { throw je("tried to put a value to the " + key + " property on a " + target.getClass().getName()); if (key == null) throw je("tried to assign \"" + (val==null?"(null)":val.toString()) + "\" to the null key"); + Trap t = null; - if (target instanceof JS) { - t = ((JS)target).getTrap(key); - while (t != null && t.f.numFormalArgs == 0) t = t.next; - } else if (target instanceof Trap.TrapScope && key.equals("cascade")) { + if (target instanceof Trap.TrapScope && key.equals("cascade")) { Trap.TrapScope ts = (Trap.TrapScope)target; t = ts.t.next; ts.cascadeHappened = true; while (t != null && t.f.numFormalArgs == 0) t = t.next; - if (t == null) target = ts.t.trapee; + if (t == null) { target = ts.t.trapee; key = ts.t.name; } + + } else if (target instanceof Trap.TrapScope && key.equals(((Trap.TrapScope)target).t.name)) { + throw je("tried to put to " + key + " inside a trap it owns; use cascade instead"); + + } else if (target instanceof JS) { + if (target instanceof JSScope) { + JSScope p = (JSScope)target; // search the scope-path for the trap + t = p.getTrap(key); + while (t == null && p.getParentScope() != null) { p = p.getParentScope(); t = p.getTrap(key); } + } else { + t = ((JS)target).getTrap(key); + } + + while (t != null && t.f.numFormalArgs == 0) t = t.next; // find the first write trap + if (t != null) { + stack.push(new CallMarker(this)); + JSArray args = new JSArray(); + args.addElement(val); + stack.push(args); + } } if (t != null) { - stack.push(new CallMarker(this)); - JSArray args = new JSArray(); - args.addElement(val); - stack.push(args); f = t.f; scope = new Trap.TrapScope(f.parentScope, t, val); pc = -1; @@ -248,18 +263,28 @@ class Interpreter implements ByteCodes, Tokens { break; } else if (o instanceof JS) { Trap t = null; - if (o instanceof JS) { - t = ((JS)o).getTrap(v); - while (t != null && t.f.numFormalArgs != 0) t = t.next; - } else if (o instanceof Trap.TrapScope && v.equals("cascade")) { + if (o instanceof Trap.TrapScope && v.equals("cascade")) { t = ((Trap.TrapScope)o).t.next; while (t != null && t.f.numFormalArgs != 0) t = t.next; - if (t == null) o = ((Trap.TrapScope)o).t.trapee; + if (t == null) { v = ((Trap.TrapScope)o).t.name; o = ((Trap.TrapScope)o).t.trapee; } + + } else if (o instanceof JS) { + if (o instanceof JSScope) { + JSScope p = (JSScope)o; // search the scope-path for the trap + t = p.getTrap(v); + while (t == null && p.getParentScope() != null) { p = p.getParentScope(); t = p.getTrap(v); } + } else { + t = ((JS)o).getTrap(v); + } + + while (t != null && t.f.numFormalArgs != 0) t = t.next; // get first read trap + if (t != null) { + stack.push(new CallMarker(this)); + JSArray args = new JSArray(); + stack.push(args); + } } if (t != null) { - stack.push(new CallMarker(this)); - JSArray args = new JSArray(); - stack.push(args); f = t.f; scope = new Trap.TrapScope(f.parentScope, t, null); ((Trap.TrapScope)scope).cascadeHappened = true; @@ -285,6 +310,10 @@ class Interpreter implements ByteCodes, Tokens { if (object == JS.METHOD) { method = stack.pop(); object = stack.pop(); + } else if (object == null) { + Object name = stack.pop(); + stack.pop(); + throw new JSExn("function '"+name+"' not found"); } else { stack.pop(); stack.pop(); @@ -524,6 +553,9 @@ class Interpreter implements ByteCodes, Tokens { // Operations on Primitives ////////////////////////////////////////////////////////////////////// static Object callMethodOnPrimitive(Object o, Object method, Object arg0, Object arg1, Object arg2, Object[] rest, int alength) throws JSExn { + if (method == null || !(method instanceof String) || "".equals(method)) + throw new JSExn("attempt to call a non-existant method on a primitive"); + if (o instanceof Number) { //#switch(method) case "toFixed": throw new JSExn("toFixed() not implemented");