more trap cleanup, brian back putAndTrigger...
authorbrian <brian@brianweb.net>
Wed, 7 Jul 2004 07:36:33 +0000 (07:36 +0000)
committerbrian <brian@brianweb.net>
Wed, 7 Jul 2004 07:36:33 +0000 (07:36 +0000)
darcs-hash:20040707073633-24bed-b0056b5de9e6dbf2fc713ad6869df45d30f1af18.gz

src/org/ibex/js/Interpreter.java
src/org/ibex/js/JS.java
src/org/ibex/js/Test.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);
                 }
             }
index c13d2a0..ad13a40 100644 (file)
@@ -300,17 +300,21 @@ public abstract class JS {
     /** performs a put, triggering traps if present; traps are run in an unpauseable interpreter */
     public void putAndTriggerTraps(JS key, JS value) throws JSExn {
         Trap t = getTrap(key);
-        throw new Error("FIXME");
-        /*if (t != null) t.invoke(value);
-        elese put(key, value);*/
+        if(t == null || (t = t.writeTrap()) == null) put(key,value);
+        else new Interpreter(t,value,false).resume();
     }
 
     /** performs a get, triggering traps if present; traps are run in an unpauseable interpreter */
     public JS getAndTriggerTraps(JS key) throws JSExn {
         Trap t = getTrap(key);
-        throw new Error("FIXME");
-        /*if (t != null) return t.invoke();
-        else return get(key);*/
+        if (t == null || (t = t.readTrap()) == null) return get(key);
+        else return new Interpreter(t,null,false).resume();
+    }
+    
+    public JS justTriggerTraps(JS key, JS value) throws JSExn {
+        Trap t = getTrap(key);
+        if(t == null || (t = t.writeTrap()) == null) return value;
+        else return new Interpreter(t,value,true).resume();
     }
 
     /** adds a trap, avoiding duplicates */
index 478ef8e..c432a6a 100644 (file)
@@ -32,6 +32,7 @@ public class Test extends JS {
         if(!JS.isString(key)) return null;
         if("print".equals(JS.toString(key))) return METHOD;
         if("clone".equals(JS.toString(key))) return METHOD;
+        if("firethis".equals(JS.toString(key))) return METHOD;
         if("bgget".equals(JS.toString(key))) {
             action = "bgget";
             try {
@@ -68,6 +69,15 @@ public class Test extends JS {
             return null;
         }
         if("clone".equals(JS.toString(method))) return a0 == null ? null : a0.jsclone();
+        if("firethis".equals(JS.toString(method))) {
+            String action = JS.toString(a0);
+            JS target = a1;
+            JS key = a2;
+            if(action.equals("get")) return a1.getAndTriggerTraps(key);
+            else if(action.equals("put")) a1.putAndTriggerTraps(key,JS.S("some value"));
+            else if(action.equals("trigger")) return target.justTriggerTraps(key,JS.S("some trigger value"));
+            return null;
+        }
         return null;
     }
 }