// 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;
}
switch (tok) {
case LP: { // invocation (not grouping)
- int n = parseArgs(b,0);
+ int n = parseArgs(b);
b.add(parserLine, CALL, JS.N(n));
break;
}
}
// 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);
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);
// 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