pc = ((TryMarker)o).finallyLoc - 1;
continue OUTER;
} else if (o instanceof CallMarker) {
- if (scope instanceof Trap.TrapScope) { // handles return component of a read trap
- Trap.TrapScope ts = (Trap.TrapScope)scope;
- if (retval != null && retval instanceof Boolean && ((Boolean)retval).booleanValue())
- ts.cascadeHappened = true;
- if (!ts.cascadeHappened) {
- ts.cascadeHappened = true;
- Trap t = ts.t.next;
- while (t != null && t.f.numFormalArgs == 0) t = t.next;
- if (t == null) {
- ((JS)ts.t.trapee).put(ts.t.name, ts.val);
- if (pausecount > initialPauseCount) { pc++; return null; } // we were paused
- } else {
- stack.push(o);
+ if (o instanceof TrapMarker) { // handles return component of a read trap
+ TrapMarker tm = (TrapMarker) o;
+ boolean cascade = tm.t.writeTrap() && !tm.cascadeHappened && !JS.toBoolean(retval);
+ if(cascade) {
+ Trap t = tm.t.next;
+ while(t != null && t.readTrap()) t = t.next;
+ if(t != null) {
+ tm.t = t;
+ stack.push(tm);
JSArray args = new JSArray();
- args.addElement(ts.val);
+ args.addElement(tm.val);
stack.push(args);
f = t.f;
- scope = new Trap.TrapScope(f.parentScope, t, ts.val);
+ scope = new JSScope(f.parentScope);
pc = -1;
continue OUTER;
+ } else {
+ tm.trapee.put(tm.key,tm.val);
}
}
}
pc = ((CallMarker)o).pc - 1;
f = (JSFunction)((CallMarker)o).f;
stack.push(retval);
+ if (pausecount > initialPauseCount) { pc++; return null; } // we were paused
continue OUTER;
}
}
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");
+
+ if (target instanceof String || target instanceof Number || target instanceof Boolean) throw new JSExn("can't put values to primitives");
+ if(!(target instanceof JS)) throw new Error("should never happen");
Trap t = null;
- Trap.TrapScope ts = null;
- if (target instanceof JSScope && key.equals("cascade")) {
- JSScope p = (JSScope)target; // search the scope-path for the trap
- if (target instanceof Trap.TrapScope) {
- ts = (Trap.TrapScope)target;
- } else {
- while (ts == null && p.getParentScope() != null) {
- p = p.getParentScope();
- if (p instanceof Trap.TrapScope) ts = (Trap.TrapScope)p;
- }
- }
- if(ts != null) {
- t = ts.t.next;
- ts.cascadeHappened = true;
- while (t != null && t.f.numFormalArgs == 0) t = t.next;
- if (t == null) { target = ts.t.trapee; key = ts.t.name; }
+ TrapMarker tm = null;
+ if(target instanceof JSScope && key.equals("cascade")) {
+ Object o=null;
+ int i;
+ for(i=stack.size()-1;i>=0;i--) if((o = stack.elementAt(i)) instanceof CallMarker) break;
+ if(i==0) throw new Error("didn't find a call marker while doing cascade");
+ if(o instanceof TrapMarker) {
+ tm = (TrapMarker) o;
+ target = tm.trapee;
+ key = tm.key;
+ tm.cascadeHappened = true;
+ t = tm.t;
+ if(t.readTrap()) throw new JSExn("can't put to cascade in a read trap");
+ t = t.next;
+ while(t != null && t.readTrap()) t = t.next;
}
}
- if(ts == null) {
- 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(tm == null) { // didn't find a trap marker, try to find a trap
+ t = target instanceof JSScope ? t = ((JSScope)target).top().getTrap(key) : ((JS)target).getTrap(key);
+ while(t != null && t.readTrap()) t = t.next;
}
- if (t != null) {
- stack.push(new CallMarker(this));
- if(stack.size() > MAX_STACK_SIZE) throw new JSExn("stack overflow");
+
+ stack.push(val);
+
+ if(t != null) {
+ stack.push(new TrapMarker(this,t,(JS)target,key,val));
JSArray args = new JSArray();
args.addElement(val);
stack.push(args);
f = t.f;
- scope = new Trap.TrapScope(f.parentScope, t, val);
+ scope = new JSScope(f.parentScope);
pc = -1;
break;
+ } else {
+ ((JS)target).put(key,val);
+ if (pausecount > initialPauseCount) { pc++; return null; } // we were paused
+ break;
}
- ((JS)target).put(key, val);
- if (pausecount > initialPauseCount) { pc++; return null; } // we were paused
- stack.push(val);
- break;
}
case GET:
case GET_PRESERVE: {
- Object o, v;
+ Object target, key;
if (op == GET) {
- v = arg == null ? stack.pop() : arg;
- o = stack.pop();
+ key = arg == null ? stack.pop() : arg;
+ target = stack.pop();
} else {
- v = stack.pop();
- o = stack.peek();
- stack.push(v);
+ key = stack.pop();
+ target = stack.peek();
+ stack.push(key);
}
Object ret = null;
- if (v == null) throw je("tried to get the null key from " + o);
- if (o == null) throw je("tried to get property \"" + v + "\" from the null object");
- if (o instanceof String || o instanceof Number || o instanceof Boolean) {
- ret = getFromPrimitive(o,v);
+ if (key == null) throw je("tried to get the null key from " + target);
+ if (target == null) throw je("tried to get property \"" + key + "\" from the null object");
+ if (target instanceof String || target instanceof Number || target instanceof Boolean) {
+ ret = getFromPrimitive(target,key);
stack.push(ret);
break;
- } else if (o instanceof JS) {
- Trap t = null;
- 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) { 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));
- if(stack.size() > MAX_STACK_SIZE) throw new JSExn("stack overflow");
- JSArray args = new JSArray();
- stack.push(args);
- f = t.f;
- scope = new Trap.TrapScope(f.parentScope, t, null);
- ((Trap.TrapScope)scope).cascadeHappened = true;
- pc = -1;
- break;
+ }
+ if(!(target instanceof JS)) throw new Error("should never happen");
+
+ Trap t = null;
+ TrapMarker tm = null;
+ if(target instanceof JSScope && key.equals("cascade")) {
+ Object o=null;
+ int i;
+ for(i=stack.size()-1;i>=0;i--) if((o = stack.elementAt(i)) instanceof CallMarker) break;
+ if(i==0) throw new Error("didn't find a call marker while doing cascade");
+ if(o instanceof TrapMarker) {
+ tm = (TrapMarker) o;
+ target = tm.trapee;
+ key = tm.key;
+ t = tm.t;
+ if(t.writeTrap()) throw new JSExn("can't do a write cascade in a read trap");
+ t = t.next;
+ while(t != null && t.writeTrap()) t = t.next;
+ if(t != null) tm.cascadeHappened = true;
}
- ret = ((JS)o).get(v);
- if (ret == JS.METHOD) ret = new Stub((JS)o, v);
- if (pausecount > initialPauseCount) { pc++; return null; } // we were paused
+ }
+ if(tm == null) { // didn't find a trap marker, try to find a trap
+ t = target instanceof JSScope ? t = ((JSScope)target).top().getTrap(key) : ((JS)target).getTrap(key);
+ while(t != null && t.writeTrap()) t = t.next;
+ }
+
+ if(t != null) {
+ stack.push(new TrapMarker(this,t,(JS)target,key,null));
+ stack.push(new JSArray());
+ f = t.f;
+ scope = new JSScope(f.parentScope);
+ pc = -1;
+ break;
+ } else {
+ ret = ((JS)target).get(key);
+ if (ret == JS.METHOD) ret = new Stub((JS)target, key);
stack.push(ret);
+ if (pausecount > initialPauseCount) { pc++; return null; } // we were paused
break;
}
- throw je("tried to get property " + v + " from a " + o.getClass().getName());
}
case CALL: case CALLMETHOD: {
}
default: {
+ if(op == BITOR) throw new Error("pc: " + pc + " of " + f);
Object right = stack.pop();
Object left = stack.pop();
switch(op) {
public CallMarker(Interpreter cx) { pc = cx.pc + 1; scope = cx.scope; f = cx.f; }
}
+ public static class TrapMarker extends CallMarker {
+ Trap t;
+ JS trapee;
+ Object key;
+ Object val;
+ boolean cascadeHappened;
+ public TrapMarker(Interpreter cx, Trap t, JS trapee, Object key, Object val) {
+ super(cx);
+ this.t = t;
+ this.trapee = trapee;
+ this.key = key;
+ this.val = val;
+ }
+ }
+
public static class CatchMarker { }
private static CatchMarker catchMarker = new CatchMarker();