import java.util.*;
import org.xwt.js.*;
import org.xwt.util.*;
+import java.io.*;
/**
* This class encapsulates a single trap placed on a given node. The
// Static Data //////////////////////////////////////////////////////////////
+ private static JS.CompiledFunction cascadeHelper = null;
+ private static String cascadeHelperText =
+ "return function(q) { var ret = arguments.doTrap;" +
+ "if (ret != false && !arguments.didCascade) arguments.cascade = q; };";
+ static {
+ try {
+ cascadeHelper = JS.parse("cascadeHelper", 1, new StringReader(cascadeHelperText));
+ cascadeHelper = (JS.CompiledFunction)new JS.Context(cascadeHelper, null, null).resume(null);
+ } catch (Exception e) {
+ Log.log(Trap.class, e);
+ }
+ }
+
/** List of properties that cannot be trapped */
private static final Hash PROHIBITED = new Hash(120, 3);
if (t.f == f) return;
// actually place the trap
- Trap t = new Trap();
- t.next = (Trap)trapee.get(name, Trap.class);
- trapee.put(name, Trap.class, t);
- t.trapee = trapee;
- t.name = name;
- t.f = f;
+ trapee.put2(name, Trap.class, new Trap(trapee, name.toString(), f, (Trap)trapee.get(name, Trap.class)));
}
*/
static void delTrap(Box trapee, Object name, JS.CompiledFunction f) {
Trap t = (Trap)trapee.get(name, Trap.class);
- if (t.f == f) {
- trapee.put(name, Trap.class, t.next);
- return;
- }
+ if (t.f == f) { trapee.put2(name, Trap.class, t.next); return; }
for(; t.next != null; t = t.next)
- if (t.next.f == f) {
- t.next = t.next.next;
- return;
- }
+ if (t.next.f == f) { t.next = t.next.next; return; }
Log.logJS("warning: tried to remove a trap that had not been placed");
}
// Instance Methods //////////////////////////////////////////////////////////////////////////
- private Trap() { }
+ private Trap(Box b, String n, JS.CompiledFunction f, Trap nx)
+ { trapee = b; name = n; this.f = f; this.next = nx; }
+
+ // Read Traps //////////////////////////////////////////////////////////////////////
- public Object perform() throws JS.Exn {
+ public Object perform() {
if (f.getNumFormalArgs() > 0) return cascade();
- return f.call(new TrapArgs(this));
- }
-
- public void perform(Object val) throws JS.Exn {
- if (f.getNumFormalArgs()== 0) cascade(val);
- f.call(new TrapArgs(this, val));
+ else return new JS.TailCall().set(f, new TrapArgs(this));
}
-
+
public Object cascade() {
if (next != null) return next.perform();
- return trapee.get(name, true);
+ else return trapee.get(name, true);
}
- public void cascade(Object val) {
- if (next != null) next.perform(val);
- trapee.put(name, val, true);
+ // Write Traps //////////////////////////////////////////////////////////////////////
+
+ public Object perform(Object val) {
+ if (f.getNumFormalArgs() == 0) return cascade(val);
+ else return new JS.TailCall().set(cascadeHelper, new TrapArgs(this, val));
}
+
+ public Object cascade(Object val) {
+ if (next != null) return next.perform(val);
+ else return trapee.put(name, val, true);
+ }
+
+ // Args ///////////////////////////////////////////////////////////////////////////
private static class TrapArgs extends JS.Array {
private Trap t;
+ public boolean cascadeHappened = false;
public TrapArgs(Trap t) { this.t = t; }
public TrapArgs(Trap t, Object value) { this.t = t; addElement(value); }
- public void put(Object key, Object val) {
- if (key.equals("cascade")) t.cascade(val);
- else super.put(key, val);
+ public Object put(Object key, Object val) {
+ if (key.equals("cascade")) { cascadeHappened = true; return t.cascade(val); }
+ else return super.put(key, val);
}
public Object get(Object key) {
// common case
if(!(key instanceof String)) return super.get(key);
if (key.equals("trapee")) return t.trapee;
+ if (key.equals("doTrap")) return new JS.TailCall().set(t.f, this);
+ if (key.equals("didCascade")) return cascadeHappened ? Boolean.TRUE : Boolean.FALSE;
if (key.equals("trapname")) return t.name;
if (key.equals("cascade")) return t.cascade();
+ if (key.equals("callee")) return t.f;
return super.get(key);
}
}