2003/11/13 09:15:12
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:41:18 +0000 (07:41 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:41:18 +0000 (07:41 +0000)
darcs-hash:20040130074118-2ba56-e6e75c475a5a50b7c523782e312c46977914ab91.gz

src/org/xwt/js/ByteCodes.java
src/org/xwt/js/JSContext.java
src/org/xwt/js/JSFunction.java
src/org/xwt/js/Parser.java
src/org/xwt/plat/AWT.java
src/org/xwt/util/Preprocessor.java

index a5955a5..d364d8c 100644 (file)
@@ -51,13 +51,13 @@ interface ByteCodes {
     /** discard the top stack element */
     static public final byte POP = -14;          
 
-    /** pop two elements; call stack[-n](stack[-n+1], stack[-n+2]...) where n is the number of args to the function */
+    /** pop element; call stack[top](stack[-n], stack[-n+1]...) where n is the number of args to the function */
     public static final byte CALL = -15;         
 
     /** pop an element; push a JS.JSArray containing the keys of the popped element */
     public static final byte PUSHKEYS = -16;     
 
-    /** swap the top two elements on the stack */
+    /** pops [arg+2] elements, pushes the former top element, then pushes back the rest (retaining order) */
     public static final byte SWAP = -17;         
 
     /** execute the ForthBlock pointed to by the literal in a fresh scope with parentJSScope==THIS */
@@ -76,8 +76,7 @@ interface ByteCodes {
      *  and FALSE for all subsequent iterations */
     public static final byte LOOP = -22;        
      
-    /** pop three elements off the stack; method arguments, method name, and an object to call the method on, then calls the method 
-        Has a similar effect a a GET followed by a CALL */
+    /** similar effect a a GET followed by a CALL */
     public static final byte CALLMETHOD = -23;
 
     /** finish a finally block and carry out whatever instruction initiated the finally block */
index 4e2d0b0..625c834 100644 (file)
@@ -23,12 +23,12 @@ public class JSContext {
      *  eval()
      */
     int pausecount = 0;
+    boolean pauseable;
 
-    JSFunction f = null;          ///< the currently-executing JSFunction
-    JSScope scope = null;
+    JSFunction f;                 ///< the currently-executing JSFunction
+    JSScope scope;
     Vec stack = new Vec();        ///< the object stack
     int pc = 0;                   ///< the program counter
-    boolean pauseable;
 
     public static void invokePauseable(JSFunction function) { new JSContext(function, true).invoke(new JSArray()); }
 
@@ -39,7 +39,10 @@ public class JSContext {
     }
 
     void invoke(JSArray args) {
+        JSFunction tf = f;
+        f = null;
         stack.push(new JSFunction.CallMarker(this));
+        f = tf;
         stack.push(args);
         resume();
     }
index 66b2e72..11f8031 100644 (file)
@@ -112,7 +112,13 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
             case JF: if (!JS.toBoolean(cx.stack.pop())) cx.pc += JS.toNumber(arg).intValue() - 1; break;
             case JMP: cx.pc += JS.toNumber(arg).intValue() - 1; break;
             case POP: cx.stack.pop(); break;
-            case SWAP: { Object o1 = cx.stack.pop(); Object o2 = cx.stack.pop(); cx.stack.push(o1); cx.stack.push(o2); break; }
+            case SWAP: {
+                int depth = (1 + (arg == null ? 1 : toInt(arg)));
+                Object save = cx.stack.elementAt(cx.stack.size() - 1);
+                for(int i=cx.stack.size() - 1; i > cx.stack.size() - depth; i--)
+                    cx.stack.setElementAt(cx.stack.elementAt(i-1), i);
+                cx.stack.setElementAt(save, cx.stack.size() - depth);
+                break; }
             case DUP: cx.stack.push(cx.stack.peek()); break;
             case NEWSCOPE: cx.scope = new JSScope(cx.scope); break;
             case OLDSCOPE: cx.scope = cx.scope.getParentJSScope(); break;
@@ -274,8 +280,8 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
                     cx.stack.push(v);
                 }
                 Object ret = null;
-                if (o == null) throw je("tried to get property \"" + v + "\" from the null value");
                 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 value");
                 if (o instanceof String || o instanceof Number || o instanceof Boolean) {
                     ret = Internal.getFromPrimitive(o,v);
                     cx.stack.push(ret);
@@ -309,7 +315,10 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
             }
             
             case CALL: case CALLMETHOD: {
-                int numArgs = JS.toNumber(arg).intValue();
+                int numArgs = JS.toInt(arg);
+                JSArray arguments = null;
+                Object arg0 = null;
+                Object arg1 = null;
                 Object o = cx.stack.pop();
                 if(o == null) throw je("attempted to call null");
                 Object ret;
@@ -318,14 +327,19 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
                     method = o;
                     if (method == null) throw new JS.Exn("cannot call the null method");
                     o = cx.stack.pop();
+                    System.out.println("o == " + o);
+                    System.out.println("method == " + method);
                     if(o instanceof String || o instanceof Number || o instanceof Boolean) {
-                        JSArray arguments = new JSArray();
+                        arguments = new JSArray();
                         for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(cx.stack.pop(), j);
-                        ret = Internal.callMethodOnPrimitive(o,method,arguments);
+                        System.out.println(cx.f.dump());
+                        System.out.println(cx.pc);
+                        ret = Internal.callMethodOnPrimitive(o, method, arguments);
                         cx.stack.push(ret);
                         cx.pc += 2;  // skip the GET and CALL
                         break;
                     } else if (o instanceof JSCallable) {
+                        cx.pc += 2;  // skip the GET and CALL
                         // fall through
                     } else {
                         // put the args back on the stack and let the GET followed by CALL happen
@@ -336,7 +350,7 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
 
                 } else if (o instanceof JSFunction) {
                     // FEATURE: use something similar to call0/call1/call2 here
-                    JSArray arguments = new JSArray();
+                    arguments = new JSArray();
                     for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(cx.stack.pop(), j);
                     cx.stack.push(new CallMarker(cx));
                     cx.stack.push(arguments);
@@ -346,13 +360,14 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
                     break;
                 }
 
+                if (!(o instanceof JSCallable)) throw new JS.Exn("can't call " + o + " @ " + cx.pc + "\n" + cx.f.dump());
                 JSCallable c = ((JSCallable)o);
                 switch(numArgs) {
                     case 0: ret = c.call0(method); break;
                     case 1: ret = c.call1(method, cx.stack.pop()); break;
-                    case 2: ret = c.call2(method, cx.stack.pop(), cx.stack.pop()); break;
+                    case 2: { Object first = cx.stack.pop(); ret = c.call2(method, cx.stack.pop(), first); break; }
                     default: {
-                        JSArray arguments = new JSArray();
+                        arguments = new JSArray();
                         for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(cx.stack.pop(), j);
                         ret = c.call(method, arguments);
                         if (cx.pausecount > initialPauseCount) return null;   // we were paused
@@ -360,7 +375,6 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
                     }
                 }
                 cx.stack.push(ret);
-                if (method != null) cx.pc += 2;  // skip the GET and CALL if this was a GETCALL
 
                 break;
             }
index ffb12d8..b3c1742 100644 (file)
@@ -350,9 +350,9 @@ class Parser extends Lexer implements ByteCodes {
             break;
         }
         case LP: {
-            int n = parseArgs(b, false);
+            int n = parseArgs(b);
 
-            // if the object supports GETCALL, we use this, and jump over the following two instructions
+            // if the object supports CALLMETHOD, we use this, and jump over the following two instructions
             b.add(parserLine,CALLMETHOD,new Integer(n));
             b.add(parserLine,GET);
             b.add(parserLine,CALL,new Integer(n));
@@ -397,7 +397,7 @@ class Parser extends Lexer implements ByteCodes {
 
         switch (tok) {
         case LP: {  // invocation (not grouping)
-            int n = parseArgs(b, true);
+            int n = parseArgs(b);
             b.add(parserLine, CALL, new Integer(n));
             break;
         }
@@ -476,13 +476,13 @@ class Parser extends Lexer implements ByteCodes {
     
     // parse a set of comma separated function arguments, assume LP has already been consumed
     // if swap is true, (because the function is already on the stack) we will SWAP after each argument to keep it on top
-    private int parseArgs(JSFunction b, boolean swap) throws IOException {
+    private int parseArgs(JSFunction b) throws IOException {
         int i = 0;
         while(peekToken() != RP) {
             i++;
             if (peekToken() != COMMA) {
                 startExpr(b, NO_COMMA);
-                if (swap) b.add(parserLine, SWAP);
+                b.add(parserLine, SWAP, new Integer(2));
                 if (peekToken() == RP) break;
             }
             consume(COMMA);
index cca1209..dac9e57 100644 (file)
@@ -280,6 +280,7 @@ public class AWT extends JVM {
 
         AWTSurface(Box root, boolean framed) {
             super(root);
+            System.out.println("Y");
             try {
                 if (framed) window = frame = new InnerFrame();
                 else window = new InnerWindow();
index 47c3134..5232be5 100644 (file)
@@ -141,7 +141,7 @@ public class Preprocessor {
                 String prefixPlusOne = ((String)keys.elementAt(i)).substring(0, prefix.length() + 1);
                 if (i<keys.size()-1 && prefixPlusOne.equals((((String)keys.elementAt(i + 1)).substring(0, prefix.length() + 1)))) {
                     System.out.println("case \'" + prefixPlusOne.charAt(prefixPlusOne.length() - 1) + "\': {");
-                    System.out.println("switch(neverUseThis.charAt(" + prefix.length() + ")) {");
+                    System.out.println("switch(neverUseThis.charAt(" + (prefix.length()+1) + ")) {");
                     buildTrie(prefixPlusOne, cases);
                     System.out.println("} break; }");
                     while(i<keys.size() && prefixPlusOne.equals(((String)keys.elementAt(i)).substring(0, prefix.length() + 1))) i++;