better enumeration, no need for SWAP(n>1)
[org.ibex.core.git] / src / org / ibex / js / Parser.java
index bcc5033..dce9a24 100644 (file)
@@ -432,7 +432,7 @@ class Parser extends Lexer implements ByteCodes {
             // first.  If the object supports method calls, it will
             // return JS.METHOD
             b.add(parserLine, GET_PRESERVE);
-            int n = parseArgs(b,0);
+            int n = parseArgs(b);
             b.add(parserLine, CALLMETHOD, JS.N(n));
             break;
         }
@@ -475,7 +475,7 @@ class Parser extends Lexer implements ByteCodes {
 
         switch (tok) {
         case LP: {  // invocation (not grouping)
-            int n = parseArgs(b,0);
+            int n = parseArgs(b);
             b.add(parserLine, CALL, JS.N(n));
             break;
         }
@@ -553,14 +553,12 @@ 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, int pushdown) throws IOException {
+    private int parseArgs(JSFunction b) throws IOException {
         int i = 0;
         while(peekToken() != RP) {
             i++;
             if (peekToken() != COMMA) {
                 startExpr(b, NO_COMMA);
-                if(pushdown != 0) b.add(parserLine, SWAP, JS.N(pushdown));
                 if (peekToken() == RP) break;
             }
             consume(COMMA);
@@ -849,55 +847,32 @@ class Parser extends Lexer implements ByteCodes {
                 consume(RP);
                 
                 b.add(parserLine, PUSHKEYS);
-                b.add(parserLine, DUP); 
-                b.add(parserLine, LITERAL, JSString.intern("length"));
-                b.add(parserLine, GET);
-                // Stack is now: n, keys, obj, ...
                 
                 int size = b.size;
                 b.add(parserLine, LOOP);
                 b.add(parserLine, POP);
-                // Stack is now: LoopMarker, n, keys, obj, ...
-                // NOTE: This will break if the interpreter ever becomes more strict 
-                //       and prevents bytecode from messing with the Markers
-                b.add(parserLine, SWAP, JS.N(3));
-                // Stack is now: Tn, keys, obj, LoopMarker, ...
-                
-                b.add(parserLine, LITERAL, JS.N(1));
-                b.add(parserLine, SUB);
-                b.add(parserLine, DUP);
-                // Stack is now: index, keys, obj, LoopMarker
-                b.add(parserLine, LITERAL, JS.ZERO);
-                b.add(parserLine, LT);
-                // Stack is now index<0, index, keys, obj, LoopMarker, ...
-                
-                b.add(parserLine, JF, JS.N(5)); // if we're >= 0 jump 5 down (to NEWSCOPE)
-                // Move the LoopMarker back  into place - this is sort of ugly
-                b.add(parserLine, SWAP, JS.N(3));
-                b.add(parserLine, SWAP, JS.N(3));
-                b.add(parserLine, SWAP, JS.N(3));
-                // Stack is now: LoopMarker, -1, keys, obj, ...
-                b.add(parserLine, BREAK);
                 
+                b.add(parserLine,SWAP); // get the keys enumeration object on top
+                b.add(parserLine,DUP);
+                b.add(parserLine,GET,JS.S("hasMoreElements"));
+                int size2 = b.size;
+                b.add(parserLine,JT);
+                b.add(parserLine,SWAP);
+                b.add(parserLine,BREAK);
+                b.set(size2, JS.N(b.size - size2));
+                b.add(parserLine,DUP);
+                b.add(parserLine,GET,JS.S("nextElement"));
+
                 b.add(parserLine, NEWSCOPE);
-                if(hadVar) {
-                    b.add(parserLine, DECLARE, JSString.intern(varName));
-                    b.add(parserLine, POP);
-                }
                 
-                // Stack is now: index, keys, obj, LoopMarker, ...
-                b.add(parserLine, GET_PRESERVE);     // key, index, keys, obj, LoopMarker, ...
-                b.add(parserLine, TOPSCOPE);         // scope, key, index, keys, obj, LoopMarker, ...
-                b.add(parserLine, SWAP);             // key, scope, index, keys, obj, LoopMarker, ...
-                b.add(parserLine, LITERAL, JSString.intern(varName)); // varName, key, scope, index, keys, obj, LoopMaker, ...
-                b.add(parserLine, SWAP);             // key, varName, scope, index, keys, obj, LoopMarker, ...
-                b.add(parserLine, PUT);              // key, scope, index, keys, obj, LoopMarker, ...
-                b.add(parserLine, POP);              // scope, index, keys, obj, LoopMarker
-                b.add(parserLine, POP);              // index, keys, obj, LoopMarker, ...
-                // Move the LoopMarker back into place - this is sort of ugly
-                b.add(parserLine, SWAP, JS.N(3));
-                b.add(parserLine, SWAP, JS.N(3));
-                b.add(parserLine, SWAP, JS.N(3));
+                b.add(parserLine,TOPSCOPE);
+                b.add(parserLine,SWAP);
+                b.add(parserLine, hadVar ? DECLARE : LITERAL, JSString.intern(varName));
+                b.add(parserLine,SWAP);
+                b.add(parserLine,PUT);
+                b.add(parserLine,POP);
+                b.add(parserLine,POP);
+                b.add(parserLine,SWAP);
                 
                 parseStatement(b, null);
                 
@@ -906,10 +881,7 @@ class Parser extends Lexer implements ByteCodes {
                 // jump here on break
                 b.set(size, JS.N(b.size - size));
                 
-                b.add(parserLine, POP); // N
-                b.add(parserLine, POP); // KEYS
-                b.add(parserLine, POP); // OBJ
-                
+                b.add(parserLine, POP);
             } else {
                 if (hadVar) pushBackToken(VAR, null);                    // yeah, this actually matters
                 b.add(parserLine, NEWSCOPE);                             // grab a fresh scope