2003/11/13 05:04:22
[org.ibex.core.git] / src / org / xwt / js / Parser.java
index 5e37596..ffb12d8 100644 (file)
@@ -4,8 +4,10 @@ package org.xwt.js;
 import org.xwt.util.*;
 import java.io.*;
 
+// FEATURE intern Integers/Numbers
+
 /**
- *  Parses a stream of lexed tokens into a tree of Function's.
+ *  Parses a stream of lexed tokens into a tree of JSFunction's.
  *
  *  There are three kinds of things we parse: blocks, statements, and
  *  expressions.
@@ -73,7 +75,7 @@ class Parser extends Lexer implements ByteCodes {
 
     /** for debugging */
     public static void main(String[] s) throws Exception {
-        Function block = new Function("stdin", 0, new InputStreamReader(System.in), null);
+        JSFunction block = new JSFunction("stdin", 0, new InputStreamReader(System.in), null);
         if (block == null) return;
         System.out.println(block);
     }
@@ -142,14 +144,14 @@ class Parser extends Lexer implements ByteCodes {
      *  bytecodes for that expression to <tt>appendTo</tt>; the
      *  appended bytecodes MUST grow the stack by exactly one element.
      */ 
-    private void startExpr(Function appendTo, int minPrecedence) throws IOException {
+    private void startExpr(JSFunction appendTo, int minPrecedence) throws IOException {
         int saveParserLine = parserLine;
         _startExpr(appendTo, minPrecedence);
         parserLine = saveParserLine;
     }
-    private void _startExpr(Function appendTo, int minPrecedence) throws IOException {
+    private void _startExpr(JSFunction appendTo, int minPrecedence) throws IOException {
         int tok = getToken();
-        Function b = appendTo;
+        JSFunction b = appendTo;
 
         switch (tok) {
         case -1: throw pe("expected expression");
@@ -200,7 +202,12 @@ class Parser extends Lexer implements ByteCodes {
                 b.pop();
             else
                 throw pe("prefixed increment/decrement can only be performed on a valid assignment target");
-            b.add(parserLine, tok, Boolean.TRUE);
+            b.add(parserLine, GET_PRESERVE, Boolean.TRUE);
+            b.add(parserLine, LITERAL, new Integer(1));
+            b.add(parserLine, tok == INC ? ADD : SUB, null);
+            b.add(parserLine, PUT, null);
+            b.add(parserLine, SWAP, null);
+            b.add(parserLine, POP, null);
             break;
         }
         case BANG: case BITNOT: case TYPEOF: {
@@ -236,7 +243,7 @@ class Parser extends Lexer implements ByteCodes {
         case FUNCTION: {
             consume(LP);
             int numArgs = 0;
-            Function b2 = new Function(sourceName, parserLine, null, null);
+            JSFunction b2 = new JSFunction(sourceName, parserLine, null, null);
             b.add(parserLine, NEWFUNCTION, b2);
 
             // function prelude; arguments array is already on the stack
@@ -272,7 +279,7 @@ class Parser extends Lexer implements ByteCodes {
             b2.add(parserLine, POP);                                      // pop off TOPSCOPE
             
            if(peekToken() != LC)
-                throw pe("Functions must have a block surrounded by curly brackets");
+                throw pe("JSFunctions must have a block surrounded by curly brackets");
                 
             parseBlock(b2, null);                                   // the function body
 
@@ -296,12 +303,12 @@ class Parser extends Lexer implements ByteCodes {
      *  expression that modifies the assignable.  This method always
      *  decreases the stack depth by exactly one element.
      */
-    private void continueExprAfterAssignable(Function b,int minPrecedence) throws IOException {
+    private void continueExprAfterAssignable(JSFunction b,int minPrecedence) throws IOException {
         int saveParserLine = parserLine;
         _continueExprAfterAssignable(b,minPrecedence);
         parserLine = saveParserLine;
     }
-    private void _continueExprAfterAssignable(Function b,int minPrecedence) throws IOException {
+    private void _continueExprAfterAssignable(JSFunction b,int minPrecedence) throws IOException {
         if (b == null) throw new Error("got null b; this should never happen");
         int tok = getToken();
         if (minPrecedence != -1 && (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok])))
@@ -325,7 +332,14 @@ class Parser extends Lexer implements ByteCodes {
             break;
         }
         case INC: case DEC: { // postfix
-            b.add(parserLine, tok, Boolean.FALSE);
+            b.add(parserLine, GET_PRESERVE, Boolean.TRUE);
+            b.add(parserLine, LITERAL, new Integer(1));
+            b.add(parserLine, tok == INC ? ADD : SUB, null);
+            b.add(parserLine, PUT, null);
+            b.add(parserLine, SWAP, null);
+            b.add(parserLine, POP, null);
+            b.add(parserLine, LITERAL, new Integer(1));
+            b.add(parserLine, tok == INC ? SUB : ADD, null);   // undo what we just did, since this is postfix
             break;
         }
         case ASSIGN: {
@@ -336,12 +350,12 @@ class Parser extends Lexer implements ByteCodes {
             break;
         }
         case LP: {
-            int n = parseArgs(b);
+            int n = parseArgs(b, false);
 
             // if the object supports GETCALL, 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_REVERSED,new Integer(n));
+            b.add(parserLine,CALL,new Integer(n));
             break;
         }
         default: {
@@ -367,12 +381,12 @@ class Parser extends Lexer implements ByteCodes {
      *  If any bytecodes are appended, they will not alter the stack
      *  depth.
      */
-    private void continueExpr(Function b, int minPrecedence) throws IOException {
+    private void continueExpr(JSFunction b, int minPrecedence) throws IOException {
         int saveParserLine = parserLine;
         _continueExpr(b, minPrecedence);
         parserLine = saveParserLine;
     }
-    private void _continueExpr(Function b, int minPrecedence) throws IOException {
+    private void _continueExpr(JSFunction b, int minPrecedence) throws IOException {
         if (b == null) throw new Error("got null b; this should never happen");
         int tok = getToken();
         if (tok == -1) return;
@@ -383,7 +397,7 @@ class Parser extends Lexer implements ByteCodes {
 
         switch (tok) {
         case LP: {  // invocation (not grouping)
-            int n = parseArgs(b);
+            int n = parseArgs(b, true);
             b.add(parserLine, CALL, new Integer(n));
             break;
         }
@@ -461,12 +475,14 @@ class Parser extends Lexer implements ByteCodes {
     }
     
     // parse a set of comma separated function arguments, assume LP has already been consumed
-    private int parseArgs(Function b) throws IOException {
+    // 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 {
         int i = 0;
         while(peekToken() != RP) {
             i++;
             if (peekToken() != COMMA) {
                 startExpr(b, NO_COMMA);
+                if (swap) b.add(parserLine, SWAP);
                 if (peekToken() == RP) break;
             }
             consume(COMMA);
@@ -476,13 +492,13 @@ class Parser extends Lexer implements ByteCodes {
     }
     
     /** Parse a block of statements which must be surrounded by LC..RC. */
-    void parseBlock(Function b) throws IOException { parseBlock(b, null); }
-    void parseBlock(Function b, String label) throws IOException {
+    void parseBlock(JSFunction b) throws IOException { parseBlock(b, null); }
+    void parseBlock(JSFunction b, String label) throws IOException {
         int saveParserLine = parserLine;
         _parseBlock(b, label);
         parserLine = saveParserLine;
     }
-    void _parseBlock(Function b, String label) throws IOException {
+    void _parseBlock(JSFunction b, String label) throws IOException {
         if (peekToken() == -1) return;
         else if (peekToken() != LC) parseStatement(b, null);
         else {
@@ -493,12 +509,12 @@ class Parser extends Lexer implements ByteCodes {
     }
 
     /** Parse a single statement, consuming the RC or SEMI which terminates it. */
-    void parseStatement(Function b, String label) throws IOException {
+    void parseStatement(JSFunction b, String label) throws IOException {
         int saveParserLine = parserLine;
         _parseStatement(b, label);
         parserLine = saveParserLine;
     }
-    void _parseStatement(Function b, String label) throws IOException {
+    void _parseStatement(JSFunction b, String label) throws IOException {
         int tok = peekToken();
         if (tok == -1) return;
         switch(tok = getToken()) {
@@ -724,8 +740,8 @@ class Parser extends Lexer implements ByteCodes {
                 b.add(parserLine, NEWSCOPE);                             // grab a fresh scope
                     
                 parseStatement(b, null);                                 // initializer
-                Function e2 =                                    // we need to put the incrementor before the test
-                    new Function(sourceName, parserLine, null, null);  // so we save the test here
+                JSFunction e2 =                                    // we need to put the incrementor before the test
+                    new JSFunction(sourceName, parserLine, null, null);  // so we save the test here
                 if (peekToken() != SEMI)
                     startExpr(e2, -1);
                 else