2003/06/29 21:20:38
[org.ibex.core.git] / src / org / xwt / js / CompiledFunctionImpl.java
index 9912ab1..5aff71a 100644 (file)
@@ -53,7 +53,8 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
             p.parseStatement(this, null);
             if (s == size()) break;
         }
-        add(-1, Tokens.RETURN);
+        add(-1, LITERAL, null); 
+        add(-1, RETURN);
     }
     
     public Object call(JS.Array args) throws JS.Exn { return call(args, new FunctionScope(sourceName, parentScope)); }
@@ -67,7 +68,10 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
             cx.stack.push(args);
             eval(scope);
             Object ret = cx.stack.pop();
-            if (cx.stack.size() > size) Log.logJS(this, "warning, stack grew by " + (cx.stack.size() - size) + " elements during call");
+            // FIXME: if we catch an exception in Java, JS won't notice and the stack will be messed up
+            if (cx.stack.size() > size)
+                // this should never happen
+                throw new Error("ERROR: stack grew by " + (cx.stack.size() - size) + " elements during call");
             return ret;
         } finally {
             cx.currentCompiledFunction = saved;
@@ -94,17 +98,23 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
         size++;
         return this;
     }
+    
+    public int getLine(int pc) {
+        if(pc < 0 || pc >= size) return -1;
+        return line[pc];
+    }
 
 
     // Invoking the Bytecode ///////////////////////////////////////////////////////
         
-    int pc = 0;
     void eval(JS.Scope s) {
         final JS.Thread cx = JS.Thread.fromJavaThread(java.lang.Thread.currentThread());
         final Vec t = cx.stack;
+        int pc;
+        int lastPC = -1;
         OUTER: for(pc=0; pc<size; pc++) {
             String label = null;
-            cx.line = line[pc];
+            cx.pc = lastPC = pc;
             switch(op[pc]) {
             case LITERAL: t.push(arg[pc]); break;
             case OBJECT: t.push(new JS.Obj()); break;
@@ -343,8 +353,32 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                 } }
             }
         }
+        // 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. Last PC was " + lastPC);
     }
 
+    // Debugging //////////////////////////////////////////////////////////////////////
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer(1024);
+        sb.append("\n" + sourceName + ": " + firstLine + "\n");
+        for (int i=0; i < size; i++) {
+            sb.append(i);
+            sb.append(": ");
+            if (op[i] < 0)
+                sb.append(bytecodeToString[-op[i]]);
+            else
+                sb.append(codeToString[op[i]]);
+            sb.append(" ");
+            sb.append(arg[i] == null ? "(no arg)" : arg[i]);
+            if((op[i] == JF || op[i] == JT || op[i] == JMP) && arg[i] != null && arg[i] instanceof Number) {
+                sb.append(" jump to ");
+                sb.append(i+((Number) arg[i]).intValue());
+            }
+            sb.append("\n");
+        }
+        return sb.toString();
+    } 
 
     // Helpers for Number, String, and Boolean ////////////////////////////////////////
 
@@ -405,8 +439,8 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
     // Exception Stuff ////////////////////////////////////////////////////////////////
 
     static class EvaluatorException extends RuntimeException { public EvaluatorException(String s) { super(s); } }
-    EvaluatorException ee(String s) { throw new EvaluatorException(sourceName + ":" + line[pc] + " " + s); }
-    JS.Exn je(String s) { throw new JS.Exn(sourceName + ":" + line[pc] + " " + s); }
+    EvaluatorException ee(String s) { throw new EvaluatorException(sourceName + ":" + JS.Thread.currentJSThread().getLine() + " " + s); }
+    JS.Exn je(String s) { throw new JS.Exn(sourceName + ":" + JS.Thread.currentJSThread().getLine() + " " + s); }
 
 
     // FunctionScope /////////////////////////////////////////////////////////////////