2003/06/09 00:07:40
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:00:54 +0000 (07:00 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:00:54 +0000 (07:00 +0000)
darcs-hash:20040130070054-2ba56-ae17578ebe8ef8e861c29d3a7affa6a7aefd65fb.gz

src/org/xwt/js/ByteCodeBlock.java
src/org/xwt/js/JS.java
src/org/xwt/js/Lexer.java
src/org/xwt/js/Parser.java
src/org/xwt/js/Tokens.java

index a0e675c..5813274 100644 (file)
@@ -39,7 +39,6 @@ class ByteCodeBlock implements ByteCodes, Tokens {
         return this;
     }
         
-    public Object eval(final JS.Scope s) throws ControlTransferException, JS.Exn { return eval(s, new Vec()); }
     public Object eval(final JS.Scope s, Vec t) throws ControlTransferException {
         for(int i=0; i<size; i++) switch(op[i]) {
             case LABEL: break;
@@ -54,17 +53,29 @@ class ByteCodeBlock implements ByteCodes, Tokens {
             case POP: t.pop(); break;
             case SWAP: { Object o1 = t.pop(); Object o2 = t.pop(); t.push(o1); t.push(o2); break; }
             case DUP: t.push(t.peek()); break;
-            case SCOPE: t.push(((ByteCodeBlock)arg[i]).eval(new JS.Scope(s))); break;
+
+               // FIXME: shouldn't need its own stack
+            case SCOPE: t.push(((ByteCodeBlock)arg[i]).eval(new JS.Scope(s), new Vec())); break;
+
             case ASSERT: if (!JS.toBoolean(t.pop())) throw new EvaluatorException(line, sourceName, "assertion failed"); break;
             case RETURN: throw new ReturnException(t.pop());
             case THROW: throw new JS.Exn(t.pop());
             case TRY: break;
+
+               // FIXME: implement
             case TYPEOF: break;
+
             case BREAK: return Boolean.FALSE;
             case CONTINUE: return Boolean.TRUE;
             case BITNOT: t.push(new Long(~JS.toLong(t.pop()))); break;
             case BANG: t.push(new Boolean(!JS.toBoolean(t.pop()))); break;
 
+            case NEWFUNCTION: {
+               ByteCodeBlock bytes = (ByteCodeBlock)arg[i];
+               t.push(new JS.Function(bytes.line, bytes.sourceName, bytes, s));
+               break;
+           }
+
             case PUSHKEYS: {
                 Object o = t.peek();
                 Object[] keys = ((JS)o).keys();
@@ -81,7 +92,7 @@ class ByteCodeBlock implements ByteCodes, Tokens {
                 stack2.push(Boolean.TRUE);
                 while (true) {
                     Boolean result;
-                    try { result = (Boolean)loop.eval(new JS.Scope(s), stack2);
+                   try { result = (Boolean)loop.eval(new JS.Scope(s), stack2);
                     } catch (ContinueException c) { result = Boolean.TRUE;
                     } catch (BreakException b) { result = Boolean.FALSE; }
                     if (result == Boolean.FALSE) break;
@@ -95,7 +106,8 @@ class ByteCodeBlock implements ByteCodes, Tokens {
                 Object val = t.pop();
                 Object key = t.pop();
                 JS target = (JS)t.peek();
-                if (target == null) throw new JS.Exn("tried to put a value to the " + key + " property on the null value");
+                if (target == null)
+                   throw new EvaluatorException(line, sourceName, "tried to put a value to the " + key + " property on the null value");
                 target.put(key, val);
                 t.push(val);
                 break;
@@ -127,28 +139,6 @@ class ByteCodeBlock implements ByteCodes, Tokens {
                 break;
             }
 
-            case NEWFUNCTION: {
-                final ByteCodeBlock myBytes = (ByteCodeBlock)arg[i];
-                t.push(new JS.Function() {
-                        public String getSourceName() throws JS.Exn { return sourceName; }
-                        public int getLine() throws JS.Exn { return line; }
-                        public Object _call(final JS.Array args) throws JS.Exn, ControlTransferException {
-                            JS.Scope scope = new JS.Scope(s) {
-                                    public String getSourceName() { return sourceName; }
-                                    public Object get(Object key) throws JS.Exn {
-                                        if (key.equals("trapee")) return org.xwt.Trap.currentTrapee();
-                                        else if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction;
-                                        return super.get(key);
-                                    }
-                                };
-                           Vec stack = new Vec();
-                            stack.push(args);
-                           return myBytes.eval(scope, stack);
-                        }
-                    });
-                break;
-            }
-
             case INC: case DEC: {
                 boolean isPrefix = JS.toBoolean(arg[i]);
                 Object key = t.pop();
index ea117c4..6c9448d 100644 (file)
@@ -132,10 +132,26 @@ public abstract class JS {
     }
 
     /** Anything that is callable */
-    public static abstract class Function extends Obj {
-       public String getSourceName() throws JS.Exn { return "unknown"; }
-       public int getLine() throws JS.Exn { return -1; }
-       public abstract Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException;
+    public static class Function extends Obj {
+       ByteCodeBlock bytecodes;
+       int line;
+       String sourceName;
+       Scope parentScope;
+       public Function() { this(-1, "unknown", null, null); }
+       public Function(int line, String sourceName, ByteCodeBlock bytecodes, Scope parentScope) {
+           this.sourceName = sourceName;
+           this.line = line;
+           this.bytecodes = bytecodes;
+           this.parentScope = parentScope;
+       }
+       public String getSourceName() throws JS.Exn { return sourceName; }
+       public int getLine() throws JS.Exn { return line; }
+       public Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException {
+           if (bytecodes == null) throw new Error("tried to call() a JS.Function with bytecodes == null");
+           Vec stack = new Vec();
+           stack.push(args);
+           return bytecodes.eval(new FunctionScope(sourceName, parentScope), stack);
+       }
        public final Object call(JS.Array args) throws JS.Exn {
            Function saved = (Function)currentFunction.get(Thread.currentThread());
            currentFunction.put(Thread.currentThread(), this);
@@ -159,7 +175,7 @@ public abstract class JS {
        public String getSourceName() throws JS.Exn { return ((ByteCodeBlock)e.elementAt(0)).getSourceName(); }
        public Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException {
            Scope rootScope = (Scope)args.elementAt(0);
-           for(int i=0; i<e.size(); i++) ((ByteCodeBlock)e.elementAt(i)).eval(rootScope);
+           for(int i=0; i<e.size(); i++) ((ByteCodeBlock)e.elementAt(i)).eval(rootScope, new Vec());
            return null;
        }
        public static Script parse(Reader r, String sourceName, int line) throws IOException {
@@ -206,7 +222,16 @@ public abstract class JS {
        }
     } 
  
-
+    private class FunctionScope extends JS.Scope {
+       String sourceName;
+       public FunctionScope(String sourceName, Scope parentScope) { super(parentScope); this.sourceName = sourceName; }
+       public String getSourceName() { return sourceName; }
+       public Object get(Object key) throws JS.Exn {
+           if (key.equals("trapee")) return org.xwt.Trap.currentTrapee();
+           else if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction;
+           return super.get(key);
+       }
+    }
 } 
 
 
index f49310b..4aaf47d 100644 (file)
@@ -407,6 +407,6 @@ class Lexer implements Tokens {
     }
 
     class LexerException extends IOException {
-       public LexerException(String s) { super(sourceName + ":" + line + "," + col + " " + s); }
+       public LexerException(String s) { super(sourceName + ":" + line + "," + col + ": " + s); }
     }
 }
index 73b3590..cd665f2 100644 (file)
@@ -65,7 +65,7 @@ class Parser extends Lexer implements ByteCodes {
     /** gets a token and throws an exception if it is not <tt>code</tt> */
     public void consume(int code) throws IOException {
        if (getToken() != code)
-           throw new ParserException("expected " + codeToString[code] + ", got " + (op == -1 ? "EOL" : codeToString[op]));
+           throw new ParserException("expected " + codeToString[code] + ", got " + (op == -1 ? "EOF" : codeToString[op]));
     }
 
     /** append the largest expression beginning with prefix containing no operators of precedence below <tt>minPrecedence</tt> */
index 11508fb..e9391c1 100644 (file)
@@ -6,8 +6,6 @@ interface Tokens {
 
     // Token Constants //////////////////////////////////////////////////////////
 
-    public static final int EOL           = -1;  // end of line
-
     // arithmetic operations; also valid as bytecodes
     public static final int BITOR         = 0;   // |
     public static final int ASSIGN_BITOR  = 1;   // |=