2003/10/31 10:57:24
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:40:43 +0000 (07:40 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:40:43 +0000 (07:40 +0000)
darcs-hash:20040130074043-2ba56-824ac54b5f1b14cd63e28d2b727f88b106cdb39c.gz

src/org/xwt/Trap.java
src/org/xwt/js/CompiledFunctionImpl.java
src/org/xwt/js/JS.java
src/org/xwt/js/Parser.java

index 2895d9f..2f436c4 100644 (file)
@@ -4,6 +4,7 @@ package org.xwt;
 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
@@ -106,16 +107,27 @@ public class Trap {
             return null;
         }
     }
-    
+
+    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.Thread(cascadeHelper).resume();
+        } catch (Exception e) {
+            Log.log(Trap.class, e);
+        }
+    }
+
     public void perform(Object val) {
         try {
             if (f.getNumFormalArgs() == 0) cascade(val);
-            TrapArgs ta = new TrapArgs(this, val);
-            JS.Thread.current().setTailCall(f, ta);
-            // FIXME: re-add autocascades
-            //if (ret != Boolean.FALSE && !ta.cascadeHappened) cascade(val);
+            else JS.Thread.current().setTailCall(cascadeHelper, new TrapArgs(this, val));
         } catch (Exception e) {
             Log.log(this, "Exception thrown from within trap: " + e);
+            e.printStackTrace();
         }
     }
     
@@ -144,6 +156,8 @@ public class Trap {
             // common case
             if(!(key instanceof String)) return super.get(key);
             if (key.equals("trapee")) return t.trapee;
+            if (key.equals("doTrap")) { JS.Thread.current().setTailCall(t.f, this); return null; }
+            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;
index df1b621..2c69e1d 100644 (file)
@@ -10,7 +10,7 @@ class CompiledFunctionImpl extends JS.Obj implements ByteCodes, Tokens {
     // Fields and Accessors ///////////////////////////////////////////////
 
     /** the number of formal arguments */
-    int numFormalArgs = 0;
+    int numFormalArgs = 20;
 
     /** the source code file that this block was drawn from */
      String sourceName;
@@ -45,6 +45,7 @@ class CompiledFunctionImpl extends JS.Obj implements ByteCodes, Tokens {
         ret.arg = this.arg;
         ret.line = this.line;
         ret.size = this.size;
+        ret.numFormalArgs = this.numFormalArgs;
         return ret;
     }
 
@@ -96,10 +97,11 @@ class CompiledFunctionImpl extends JS.Obj implements ByteCodes, Tokens {
     // Invoking the Bytecode ///////////////////////////////////////////////////////
 
     /** returns false if the thread has been paused */
-    static void eval(final JS.Thread cx) throws JS.Exn {
-        OUTER: for(; cx.currentCompiledFunction == null || cx.pc<((CompiledFunctionImpl)cx.currentCompiledFunction).size; cx.pc++) {
+    static Object eval(final JS.Thread cx) throws JS.Exn {
+        OUTER: for(;; cx.pc++) {
         try {
-            if (cx.paused || cx.currentCompiledFunction == null) return;
+            if (cx.paused) return null;
+            cx.bind();
             if (cx.tailCallFunction != null) {
                 cx.stack.pop();  // discard actual return value
                 cx.pc -= 2;
@@ -111,6 +113,8 @@ class CompiledFunctionImpl extends JS.Obj implements ByteCodes, Tokens {
                 cx.scope = new FunctionScope("unknown", cx.currentCompiledFunction.parentScope);
                 cx.pc = 0;
             }
+            if (cx.currentCompiledFunction == null) return cx.stack.pop();
+            if (cx.pc >= ((CompiledFunctionImpl)cx.currentCompiledFunction).size) return cx.stack.pop();
             String label = null;
             int curOP = cx.currentCompiledFunction.op[cx.pc];
             Object curArg = cx.currentCompiledFunction.arg[cx.pc];
@@ -482,8 +486,6 @@ class CompiledFunctionImpl extends JS.Obj implements ByteCodes, Tokens {
             throw e;
         } // end try/catch
         } // end for
-        // this should never happen, we will ALWAYS have a RETURN at the end of the func
-        throw new Error("Just fell out of CompiledFunction::eval() loop.");
     }
 
     // Debugging //////////////////////////////////////////////////////////////////////
index 256c33a..ebd2e36 100644 (file)
@@ -240,10 +240,10 @@ public abstract class JS {
 
         public static JS.Thread current() { return (JS.Thread)javaThreadToJSThread.get(java.lang.Thread.currentThread()); }
 
-        public void resume() { bind(); paused = false; CompiledFunctionImpl.eval(this); }
+        public Object resume() { bind(); paused = false; Object ret = CompiledFunctionImpl.eval(this); unbind(); return ret; }
         public void pause() { paused = true; unbind(); }
         public void bind() { javaThreadToJSThread.put(java.lang.Thread.currentThread(), this); }
-        public void unbind() { if (current() == this) javaThreadToJSThread.put(java.lang.Thread.currentThread(), this); }
+        public void unbind() { if (current() == this) javaThreadToJSThread.remove(java.lang.Thread.currentThread()); }
         public int getLine() { return currentCompiledFunction == null ? -1 : currentCompiledFunction.getLine(this); }
         public String getSourceName() { return currentCompiledFunction == null ? null : currentCompiledFunction.getSourceName();  }
 
index 323d1dc..7360876 100644 (file)
@@ -248,12 +248,13 @@ class Parser extends Lexer implements ByteCodes {
             b2.add(parserLine, PUT);
 
             while(peekToken() != RP) {                                    // run through the list of argument names
+                numArgs++;
                 if (peekToken() == NAME) {
                     consume(NAME);                                        // a named argument
                     String varName = string;
                     
                     b2.add(parserLine, DUP);                              // dup the args array 
-                    b2.add(parserLine, GET, new Integer(numArgs));   // retrieve it from the arguments array
+                    b2.add(parserLine, GET, new Integer(numArgs - 1));   // retrieve it from the arguments array
                     b2.add(parserLine, TOPSCOPE);
                     b2.add(parserLine, SWAP);
                     b2.add(parserLine, DECLARE, varName);                  // declare the name
@@ -264,11 +265,10 @@ class Parser extends Lexer implements ByteCodes {
                 }
                 if (peekToken() == RP) break;
                 consume(COMMA);
-                numArgs++;
             }
             consume(RP);
 
-            b2.numFormalArgs = numArgs + 1;
+            b2.numFormalArgs = numArgs;
             b2.add(parserLine, POP);                                      // pop off the arguments array
             b2.add(parserLine, POP);                                      // pop off TOPSCOPE