X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fjs%2FParser.java;h=51b23b889a8df0b233b7a3184af3724e795a26ef;hb=b857cf06b4b1fe9a5f6200728cc1e5f94903b05a;hp=f36eda4bcf9ef3008203adc13e1458909a9de65a;hpb=3591b88b94a6bb378af3d4abe6eb5233ce583104;p=org.ibex.core.git diff --git a/src/org/ibex/js/Parser.java b/src/org/ibex/js/Parser.java index f36eda4..51b23b8 100644 --- a/src/org/ibex/js/Parser.java +++ b/src/org/ibex/js/Parser.java @@ -72,7 +72,7 @@ class Parser extends Lexer implements ByteCodes { public Parser(Reader r, String sourceName, int line) throws IOException { super(r, sourceName, line); } /** for debugging */ - public static void main(String[] s) throws Exception { + public static void main(String[] s) throws IOException { JS block = JS.fromReader("stdin", 0, new InputStreamReader(System.in)); if (block == null) return; System.out.println(block); @@ -192,7 +192,6 @@ class Parser extends Lexer implements ByteCodes { int i = 0; if (peekToken() != RB) while(true) { // iterate over the initialization values - int size = b.size; b.add(parserLine, LITERAL, JS.N(i++)); // push the index in the array to place it into if (peekToken() == COMMA || peekToken() == RB) b.add(parserLine, LITERAL, null); // for stuff like [1,,2,] @@ -318,7 +317,7 @@ class Parser extends Lexer implements ByteCodes { // attempt to continue the expression continueExpr(b, minPrecedence); } - + /* private Grammar parseGrammar(Grammar g) throws IOException { int tok = getToken(); if (g != null) @@ -349,7 +348,7 @@ class Parser extends Lexer implements ByteCodes { if (g == null) return parseGrammar(g0); return parseGrammar(new Grammar.Juxtaposition(g, g0)); } - + */ /** * Assuming that a complete assignable (lvalue) has just been * parsed and the object and key are on the stack, @@ -369,7 +368,7 @@ class Parser extends Lexer implements ByteCodes { // force the default case tok = -1; switch(tok) { - + /* case GRAMMAR: { b.add(parserLine, GET_PRESERVE); Grammar g = parseGrammar(null); @@ -383,15 +382,13 @@ class Parser extends Lexer implements ByteCodes { b.add(parserLine, PUT); break; } - + */ case ASSIGN_BITOR: case ASSIGN_BITXOR: case ASSIGN_BITAND: case ASSIGN_LSH: case ASSIGN_RSH: case ASSIGN_URSH: case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: case ASSIGN_ADD: case ASSIGN_SUB: case ADD_TRAP: case DEL_TRAP: { if (tok != ADD_TRAP && tok != DEL_TRAP) b.add(parserLine, GET_PRESERVE); startExpr(b, precedence[tok]); - int size = b.size; - if (tok != ADD_TRAP && tok != DEL_TRAP) { // tok-1 is always s/^ASSIGN_// (0 is BITOR, 1 is ASSIGN_BITOR, etc) b.add(parserLine, tok - 1, tok-1==ADD ? JS.N(2) : null); @@ -411,7 +408,7 @@ class Parser extends Lexer implements ByteCodes { b.add(parserLine, SWAP, null); b.add(parserLine, POP, null); b.add(parserLine, LITERAL, JS.N(1)); - b.add(parserLine, tok == INC ? SUB : ADD, null); // undo what we just did, since this is postfix + b.add(parserLine, tok == INC ? SUB : ADD, JS.N(2)); // undo what we just did, since this is postfix break; } case ASSIGN: { @@ -494,7 +491,7 @@ class Parser extends Lexer implements ByteCodes { break; } case OR: case AND: { - b.add(parserLine, tok == AND ? b.JF : b.JT, JS.ZERO); // test to see if we can short-circuit + b.add(parserLine, tok == AND ? JSFunction.JF : JSFunction.JT, JS.ZERO); // test to see if we can short-circuit int size = b.size; startExpr(b, precedence[tok]); // otherwise check the second value b.add(parserLine, JMP, JS.N(2)); // leave the second value on the stack and jump to the end @@ -743,7 +740,6 @@ class Parser extends Lexer implements ByteCodes { if (peekToken() != RP) { // extended Ibex catch block: catch(e faultCode "foo.bar.baz") consume(NAME); - String propName = string; b.add(parserLine, DUP); b.add(parserLine, LITERAL, string); b.add(parserLine, GET); @@ -839,37 +835,73 @@ class Parser extends Lexer implements ByteCodes { pushBackToken(tok, varName); if (forIn) { - b.add(parserLine, NEWSCOPE); // for-loops always create new scopes - b.add(parserLine, LITERAL, varName); // declare the new variable - b.add(parserLine, DECLARE); - - b.add(parserLine, LOOP); // we actually only add this to ensure that BREAK works - b.add(parserLine, POP); // discard the first-iteration indicator - int size = b.size; consume(NAME); consume(IN); - startExpr(b, -1); - b.add(parserLine, PUSHKEYS); // push the keys as an array; check the length - b.add(parserLine, LITERAL, "length"); - b.add(parserLine, GET); + startExpr(b,-1); consume(RP); - - b.add(parserLine, LITERAL, JS.N(1)); // decrement the length + + b.add(parserLine, PUSHKEYS); + b.add(parserLine, DUP); + b.add(parserLine, LITERAL, "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); - b.add(parserLine, LITERAL, JS.ZERO); // see if we've exhausted all the elements + // Stack is now: index, keys, obj, LoopMarker + b.add(parserLine, LITERAL, JS.ZERO); b.add(parserLine, LT); - b.add(parserLine, JF, JS.N(2)); - b.add(parserLine, BREAK); // if we have, then BREAK - b.add(parserLine, GET_PRESERVE); // get the key out of the keys array - b.add(parserLine, LITERAL, varName); - b.add(parserLine, PUT); // write it to this[varName] - parseStatement(b, null); // do some stuff - b.add(parserLine, CONTINUE); // continue if we fall out the bottom - - b.set(size - 1, JS.N(b.size - size + 1)); // BREAK to here - b.add(parserLine, OLDSCOPE); // restore the scope - + // 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, NEWSCOPE); + if(hadVar) { + b.add(parserLine, DECLARE, 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, 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)); + + parseStatement(b, null); + + b.add(parserLine, OLDSCOPE); + b.add(parserLine, CONTINUE); + // 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 + } else { if (hadVar) pushBackToken(VAR, null); // yeah, this actually matters b.add(parserLine, NEWSCOPE); // grab a fresh scope @@ -880,7 +912,7 @@ class Parser extends Lexer implements ByteCodes { if (peekToken() != SEMI) startExpr(e2, -1); else - e2.add(parserLine, b.LITERAL, Boolean.TRUE); // handle the for(foo;;foo) case + e2.add(parserLine, JSFunction.LITERAL, Boolean.TRUE); // handle the for(foo;;foo) case consume(SEMI); if (label != null) b.add(parserLine, LABEL, label); b.add(parserLine, LOOP); @@ -944,7 +976,7 @@ class Parser extends Lexer implements ByteCodes { // ParserException ////////////////////////////////////////////////////////////////////// - private IOException pe(String s) { return new IOException(sourceName + ":" + parserLine + " " + s); } + private IOException pe(String s) { return new IOException(sourceName + ":" + line + " " + s); } }