more trap cleanup, brian back putAndTrigger...
[org.ibex.core.git] / src / org / ibex / js / Interpreter.java
index 15d42be..6f163fa 100644 (file)
@@ -27,13 +27,22 @@ class Interpreter implements ByteCodes, Tokens {
         this.pausecount = pauseable ? 0 : -1;
         this.scope = new JSScope(f.parentScope);
         try {
-            stack.push(new CallMarker());    // the "root function returned" marker -- f==null
+            stack.push(new CallMarker(null));    // the "root function returned" marker -- f==null
             stack.push(args);
         } catch(JSExn e) {
             throw new Error("should never happen");
         }
     }
     
+    Interpreter(Trap t, JS val, boolean pauseOnPut) {
+        this.pausecount = -1;
+        try {
+            setupTrap(t,val,new TrapMarker(null,t,val,pauseOnPut));
+        } catch(JSExn e) {
+            throw new Error("should never happen");
+        }
+    }
+    
     /** this is the only synchronization point we need in order to be threadsafe */
     synchronized JS resume() throws JSExn {
         if(f == null) throw new RuntimeException("function already finished");
@@ -168,14 +177,14 @@ class Interpreter implements ByteCodes, Tokens {
                         pc = ((TryMarker)o).finallyLoc - 1;
                         continue OUTER;
                     } else if (o instanceof CallMarker) {
+                        boolean didTrapPut = false;
                         if (o instanceof TrapMarker) { // handles return component of a read trap
                             TrapMarker tm = (TrapMarker) o;
                             boolean cascade = tm.t.isWriteTrap() && !tm.cascadeHappened && !JS.toBoolean(retval);
                             if(cascade) {
                                 Trap t = tm.t.nextWriteTrap();
-                                if(t == null && tm.target instanceof JS.Clone) {
-                                    tm.target = ((JS.Clone)tm.target).clonee;
-                                    t = tm.target.getTrap(tm.key);
+                                if(t == null && tm.t.target instanceof JS.Clone) {
+                                    t = ((JS.Clone)tm.t.target).clonee.getTrap(tm.t.key);
                                     if(t != null) t = t.writeTrap();
                                 }
                                 if(t != null) {
@@ -184,7 +193,8 @@ class Interpreter implements ByteCodes, Tokens {
                                     pc--; // we increment it on the next iter
                                     continue OUTER;
                                 } else {
-                                    tm.target.put(tm.key,tm.val);
+                                    didTrapPut = true;
+                                    if(!tm.pauseOnPut) tm.t.target.put(tm.t.key,tm.val);
                                 }
                             }
                         }
@@ -192,9 +202,13 @@ class Interpreter implements ByteCodes, Tokens {
                         scope = cm.scope;
                         pc = cm.pc - 1;
                         f = cm.f;
-                        stack.push(retval);
-                        if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused
-                        if(f == null) return retval;
+                        if (didTrapPut) {
+                            if (((TrapMarker)cm).pauseOnPut) { pc++; return ((TrapMarker)cm).val; }
+                            if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused
+                        } else {
+                            stack.push(retval);
+                        }
+                        if (f == null) return retval;
                         continue OUTER;
                     }
                 }
@@ -214,8 +228,8 @@ class Interpreter implements ByteCodes, Tokens {
                     CallMarker o = stack.findCall();
                     if(o instanceof TrapMarker) {
                         tm = (TrapMarker) o;
-                        target = tm.target;
-                        key = tm.key;
+                        target = tm.t.target;
+                        key = tm.t.key;
                         tm.cascadeHappened = true;
                         t = tm.t;
                         if(t.isReadTrap()) throw new JSExn("can't do a write cascade in a read trap");
@@ -235,10 +249,11 @@ class Interpreter implements ByteCodes, Tokens {
                 stack.push(val);
                 
                 if(t != null) {
-                    setupTrap(t,val,new TrapMarker(this,t,target,key,val));
+                    setupTrap(t,val,new TrapMarker(this,t,val, tm != null && tm.pauseOnPut));
                     pc--; // we increment later
                     break;
                 } else {
+                    if (tm != null && tm.pauseOnPut) { pc++; return val; }
                     target.put(key,val);
                     if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused
                     break;
@@ -266,8 +281,8 @@ class Interpreter implements ByteCodes, Tokens {
                     CallMarker o = stack.findCall();
                     if(o instanceof TrapMarker) {
                         tm = (TrapMarker) o;
-                        target = tm.target;
-                        key = tm.key;
+                        target = tm.t.target;
+                        key = tm.t.key;
                         t = tm.t;
                         if(t.isWriteTrap()) throw new JSExn("can't do a read cascade in a write trap");
                         t = t.nextReadTrap();
@@ -284,7 +299,7 @@ class Interpreter implements ByteCodes, Tokens {
                 }
                 
                 if(t != null) {
-                    setupTrap(t,null,new TrapMarker(this,t,target,key,null));
+                    setupTrap(t,null,new TrapMarker(this,t,null));
                     pc--; // we increment later
                     break;
                 } else {
@@ -520,7 +535,7 @@ class Interpreter implements ByteCodes, Tokens {
         stack.push(cm);
         stack.push(t.isWriteTrap() ? new JSArgs(val,t.f) : new JSArgs(t.f));
         f = t.f;
-        scope = new TrapScope(t.f.parentScope,t.target,t.f,t.key);
+        scope = new TrapScope(t.f.parentScope,t);
         pc = 0;
     }
 
@@ -538,22 +553,24 @@ class Interpreter implements ByteCodes, Tokens {
         final int pc;
         final JSScope scope;
         final JSFunction f;
-        public CallMarker(Interpreter cx) { pc = cx.pc + 1; scope = cx.scope; f = cx.f; }
-        public CallMarker() { pc = -1; scope = null; f = null; }
+        public CallMarker(Interpreter cx) {
+            pc = cx == null ? -1 : cx.pc + 1;
+            scope = cx == null ? null : cx.scope;
+            f = cx == null ? null : cx.f;
+        }
     }
     
     static class TrapMarker extends CallMarker {
         Trap t;
-        JS target;
-        final JS key;
-        final JS val;
+        JS val;
         boolean cascadeHappened;
-        public TrapMarker(Interpreter cx, Trap t, JS target, JS key, JS val) {
+        final boolean pauseOnPut;
+        public TrapMarker(Interpreter cx, Trap t, JS val) { this(cx,t,val,false); } 
+        public TrapMarker(Interpreter cx, Trap t, JS val, boolean pauseOnPut) {
             super(cx);
             this.t = t;
-            this.target = target;
-            this.key = key;
             this.val = val;
+            this.pauseOnPut = pauseOnPut;
         }
     }
     
@@ -592,18 +609,16 @@ class Interpreter implements ByteCodes, Tokens {
     }
 
     static class TrapScope extends JSScope {
-        JS trapee;
-        JS callee;
-        JS trapname;
-        public TrapScope(JSScope parent, JS trapee, JS callee, JS trapname) {
-            super(parent); this.trapee = trapee; this.callee = callee; this.trapname = trapname;
+        private Trap t;
+        public TrapScope(JSScope parent, Trap t) {
+            super(parent); this.t = t;
         }
         public JS get(JS key) throws JSExn {
             if(JS.isString(key)) {
                 //#switch(JS.toString(key))
-                case "trapee": return trapee;
-                case "callee": return callee;
-                case "trapname": return trapname;
+                case "trapee": return t.target;
+                case "callee": return t.f;
+                case "trapname": return t.key;
                 //#end
             }
             return super.get(key);
@@ -685,7 +700,7 @@ class Interpreter implements ByteCodes, Tokens {
                     if(cm.f == null) break;
                     String s = cm.f.sourceName + ":" + cm.f.line[cm.pc-1];
                     if(cm instanceof Interpreter.TrapMarker) 
-                        s += " (trap on " + JS.debugToString(((Interpreter.TrapMarker)cm).key) + ")";
+                        s += " (trap on " + JS.debugToString(((Interpreter.TrapMarker)cm).t.key) + ")";
                     e.addBacktrace(s);
                 }
             }