From ae564d6e66706ba0c256a43097deb3c07ca1cc9a Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Tue, 24 Aug 2010 19:45:21 -0700 Subject: [PATCH] Refactor structured property names to pseudo-namespaces using bind --- js/narcissus/jsexec.js | 8 +- js/narcissus/jsparse.js | 1826 ++++++++++++++++++++------------------- 2 files changed, 934 insertions(+), 900 deletions(-) diff --git a/js/narcissus/jsexec.js b/js/narcissus/jsexec.js index 777ed4e48b8a..0ab9b233f420 100644 --- a/js/narcissus/jsexec.js +++ b/js/narcissus/jsexec.js @@ -85,7 +85,7 @@ Narcissus.interpreter = (function() { x2.callee = x.callee; x2.scope = x.scope; try { - x2.execute(parser.parse(new parser.VanillaBuilder, s)); + x2.execute(parser.parse(new parser.DefaultBuilder, s)); return x2.result; } catch (e if e instanceof SyntaxError || isStackOverflow(e)) { /* @@ -119,7 +119,7 @@ Narcissus.interpreter = (function() { // NB: Use the STATEMENT_FORM constant since we don't want to push this // function onto the fake compilation context. - var x = { builder: new parser.VanillaBuilder }; + var x = { builder: new parser.DefaultBuilder }; var f = parser.FunctionDefinition(t, x, false, parser.STATEMENT_FORM); var s = {object: global, parent: null}; return newFunction(f,{scope:s}); @@ -1023,7 +1023,7 @@ Narcissus.interpreter = (function() { return s; var x = new ExecutionContext(GLOBAL_CODE); - x.execute(parser.parse(new parser.VanillaBuilder, s, f, l)); + x.execute(parser.parse(new parser.DefaultBuilder, s, f, l)); return x.result; } @@ -1059,7 +1059,7 @@ Narcissus.interpreter = (function() { } } - var b = new parser.VanillaBuilder; + var b = new parser.DefaultBuilder; var x = new ExecutionContext(GLOBAL_CODE); ExecutionContext.current = x; diff --git a/js/narcissus/jsparse.js b/js/narcissus/jsparse.js index e1da444505bd..f5918bd43fe2 100644 --- a/js/narcissus/jsparse.js +++ b/js/narcissus/jsparse.js @@ -51,740 +51,771 @@ Narcissus.parser = (function() { // Set constants in the local scope. eval(definitions.consts); - /* - * The vanilla AST builder. - */ - function VanillaBuilder() { + /* + * Function.prototype.bind is not yet implemented in many browsers. + * The following definition will be removed when it is. + * + * Similar to Prototype's implementation. + */ + + function bindMethod(method, context) { + if (arguments.length < 3 && arguments[0] === undefined) + return method; + var slice = Array.prototype.slice; + var args = slice.call(arguments, 2); + // Optimization for when there's no currying. + if (args.length === 0) { + return function() { + return method.apply(context, arguments); + } + } + + return function() { + var a = slice.call(args, 0); + for (var i = 0, j = arguments.length; i < j; i++) { + a.push(arguments[i]); + } + return method.apply(context, a); + } } - VanillaBuilder.prototype = { - IF$build: function(t) { - return new Node(t, IF); - }, + function bindSubBuilders(builder, proto) { + for (var ns in proto) { + var unbound = proto[ns]; + // We do not want to bind functions like setHoists. + if (typeof unbound !== "object") + continue; + + /* + * We store the bound sub-builder as builder's own property + * so that we can have multiple builders at the same time. + */ + var bound = builder[ns] = {}; + for (var m in unbound) { + bound[m] = bindMethod(unbound[m], builder); + } + } + } + + /* + * The vanilla AST builder. + */ + + function DefaultBuilder() { + bindSubBuilders(this, DefaultBuilder.prototype); + } + + function mkBinopBuilder(type) { + return { + build: !type ? function(t) { return new Node(t); } + : function(t) { return new Node(t, type); }, + addOperand: function(n, n2) { n.push(n2); }, + finish: function(n) { } + }; + } + + DefaultBuilder.prototype = { + IF: { + build: function(t) { + return new Node(t, IF); + }, + + setCondition: function(n, e) { + n.condition = e; + }, + + setThenPart: function(n, s) { + n.thenPart = s; + }, + + setElsePart: function(n, s) { + n.elsePart = s; + }, + + finish: function(n) { + } + }, + + SWITCH: { + build: function(t) { + var n = new Node(t, SWITCH); + n.cases = []; + n.defaultIndex = -1; + return n; + }, + + setDiscriminant: function(n, e) { + n.discriminant = e; + }, + + setDefaultIndex: function(n, i) { + n.defaultIndex = i; + }, + + addCase: function(n, n2) { + n.cases.push(n2); + }, + + finish: function(n) { + } + }, + + CASE: { + build: function(t) { + return new Node(t, CASE); + }, + + setLabel: function(n, e) { + n.caseLabel = e; + }, + + initializeStatements: function(n, t) { + n.statements = new Node(t, BLOCK); + }, + + addStatement: function(n, s) { + n.statements.push(s); + }, + + finish: function(n) { + } + }, + + DEFAULT: { + build: function(t, p) { + return new Node(t, DEFAULT); + }, + + initializeStatements: function(n, t) { + n.statements = new Node(t, BLOCK); + }, + + addStatement: function(n, s) { + n.statements.push(s); + }, - IF$setCondition: function(n, e) { - n.condition = e; + finish: function(n) { + } }, - IF$setThenPart: function(n, s) { - n.thenPart = s; - }, + FOR: { + build: function(t) { + var n = new Node(t, FOR); + n.isLoop = true; + n.isEach = false; + return n; + }, - IF$setElsePart: function(n, s) { - n.elsePart = s; - }, + rebuildForEach: function(n) { + n.isEach = true; + }, - IF$finish: function(n) { - }, + // NB. This function is called after rebuildForEach, if that's called + // at all. + rebuildForIn: function(n) { + n.type = FOR_IN; + }, - SWITCH$build: function(t) { - var n = new Node(t, SWITCH); - n.cases = []; - n.defaultIndex = -1; - return n; - }, + setCondition: function(n, e) { + n.condition = e; + }, - SWITCH$setDiscriminant: function(n, e) { - n.discriminant = e; - }, + setSetup: function(n, e) { + n.setup = e || null; + }, - SWITCH$setDefaultIndex: function(n, i) { - n.defaultIndex = i; - }, + setUpdate: function(n, e) { + n.update = e; + }, - SWITCH$addCase: function(n, n2) { - n.cases.push(n2); - }, + setObject: function(n, e) { + n.object = e; + }, - SWITCH$finish: function(n) { - }, + setIterator: function(n, e, e2) { + n.iterator = e; + n.varDecl = e2; + }, - CASE$build: function(t) { - return new Node(t, CASE); - }, + setBody: function(n, s) { + n.body = s; + }, - CASE$setLabel: function(n, e) { - n.caseLabel = e; + finish: function(n) { + } }, - CASE$initializeStatements: function(n, t) { - n.statements = new Node(t, BLOCK); - }, + WHILE: { + build: function(t) { + var n = new Node(t, WHILE); + n.isLoop = true; + return n; + }, - CASE$addStatement: function(n, s) { - n.statements.push(s); - }, + setCondition: function(n, e) { + n.condition = e; + }, - CASE$finish: function(n) { - }, + setBody: function(n, s) { + n.body = s; + }, - DEFAULT$build: function(t, p) { - return new Node(t, DEFAULT); + finish: function(n) { + } }, - DEFAULT$initializeStatements: function(n, t) { - n.statements = new Node(t, BLOCK); - }, + DO: { + build: function(t) { + var n = new Node(t, DO); + n.isLoop = true; + return n; + }, - DEFAULT$addStatement: function(n, s) { - n.statements.push(s); - }, + setCondition: function(n, e) { + n.condition = e; + }, - DEFAULT$finish: function(n) { - }, + setBody: function(n, s) { + n.body = s; + }, - FOR$build: function(t) { - var n = new Node(t, FOR); - n.isLoop = true; - n.isEach = false; - return n; + finish: function(n) { + } }, - FOR$rebuildForEach: function(n) { - n.isEach = true; - }, + BREAK: { + build: function(t) { + return new Node(t, BREAK); + }, - // NB. This function is called after rebuildForEach, if that's called - // at all. - FOR$rebuildForIn: function(n) { - n.type = FOR_IN; - }, + setLabel: function(n, v) { + n.label = v; + }, - FOR$setCondition: function(n, e) { - n.condition = e; - }, + setTarget: function(n, n2) { + n.target = n2; + }, - FOR$setSetup: function(n, e) { - n.setup = e || null; + finish: function(n) { + } }, - FOR$setUpdate: function(n, e) { - n.update = e; - }, + CONTINUE: { + build: function(t) { + return new Node(t, CONTINUE); + }, - FOR$setObject: function(n, e) { - n.object = e; - }, + setLabel: function(n, v) { + n.label = v; + }, - FOR$setIterator: function(n, e, e2) { - n.iterator = e; - n.varDecl = e2; - }, + setTarget: function(n, n2) { + n.target = n2; + }, - FOR$setBody: function(n, s) { - n.body = s; + finish: function(n) { + } }, - FOR$finish: function(n) { - }, + TRY: { + build: function(t) { + var n = new Node(t, TRY); + n.catchClauses = []; + return n; + }, - WHILE$build: function(t) { - var n = new Node(t, WHILE); - n.isLoop = true; - return n; - }, + setTryBlock: function(n, s) { + n.tryBlock = s; + }, - WHILE$setCondition: function(n, e) { - n.condition = e; - }, + addCatch: function(n, n2) { + n.catchClauses.push(n2); + }, - WHILE$setBody: function(n, s) { - n.body = s; - }, + finishCatches: function(n) { + }, - WHILE$finish: function(n) { - }, + setFinallyBlock: function(n, s) { + n.finallyBlock = s; + }, - DO$build: function(t) { - var n = new Node(t, DO); - n.isLoop = true; - return n; + finish: function(n) { + } }, - DO$setCondition: function(n, e) { - n.condition = e; - }, + CATCH: { + build: function(t) { + var n = new Node(t, CATCH); + n.guard = null; + return n; + }, - DO$setBody: function(n, s) { - n.body = s; - }, + setVarName: function(n, v) { + n.varName = v; + }, - DO$finish: function(n) { - }, + setGuard: function(n, e) { + n.guard = e; + }, - BREAK$build: function(t) { - return new Node(t, BREAK); - }, + setBlock: function(n, s) { + n.block = s; + }, - BREAK$setLabel: function(n, v) { - n.label = v; + finish: function(n) { + } }, - BREAK$setTarget: function(n, n2) { - n.target = n2; - }, + THROW: { + build: function(t) { + return new Node(t, THROW); + }, - BREAK$finish: function(n) { - }, + setException: function(n, e) { + n.exception = e; + }, - CONTINUE$build: function(t) { - return new Node(t, CONTINUE); + finish: function(n) { + } }, - CONTINUE$setLabel: function(n, v) { - n.label = v; - }, + RETURN: { + build: function(t) { + return new Node(t, RETURN); + }, - CONTINUE$setTarget: function(n, n2) { - n.target = n2; - }, + setValue: function(n, e) { + n.value = e; + }, - CONTINUE$finish: function(n) { + finish: function(n) { + } }, - TRY$build: function(t) { - var n = new Node(t, TRY); - n.catchClauses = []; - return n; - }, + YIELD: { + build: function(t) { + return new Node(t, YIELD); + }, - TRY$setTryBlock: function(n, s) { - n.tryBlock = s; - }, + setValue: function(n, e) { + n.value = e; + }, - TRY$addCatch: function(n, n2) { - n.catchClauses.push(n2); + finish: function(n) { + } }, - TRY$finishCatches: function(n) { - }, + GENERATOR: { + build: function(t) { + return new Node(t, GENERATOR); + }, - TRY$setFinallyBlock: function(n, s) { - n.finallyBlock = s; - }, + setExpression: function(n, e) { + n.expression = e; + }, - TRY$finish: function(n) { - }, + setTail: function(n, n2) { + n.tail = n2; + }, - CATCH$build: function(t) { - var n = new Node(t, CATCH); - n.guard = null; - return n; + finish: function(n) { + } }, - CATCH$setVarName: function(n, v) { - n.varName = v; - }, + WITH: { + build: function(t) { + return new Node(t, WITH); + }, - CATCH$setGuard: function(n, e) { - n.guard = e; - }, + setObject: function(n, e) { + n.object = e; + }, - CATCH$setBlock: function(n, s) { - n.block = s; - }, + setBody: function(n, s) { + n.body = s; + }, - CATCH$finish: function(n) { + finish: function(n) { + } }, - THROW$build: function(t) { - return new Node(t, THROW); + DEBUGGER: { + build: function(t) { + return new Node(t, DEBUGGER); + } }, - THROW$setException: function(n, e) { - n.exception = e; - }, + SEMICOLON: { + build: function(t) { + return new Node(t, SEMICOLON); + }, - THROW$finish: function(n) { - }, + setExpression: function(n, e) { + n.expression = e; + }, - RETURN$build: function(t) { - return new Node(t, RETURN); + finish: function(n) { + } }, - RETURN$setValue: function(n, e) { - n.value = e; - }, + LABEL: { + build: function(t) { + return new Node(t, LABEL); + }, - RETURN$finish: function(n) { - }, + setLabel: function(n, e) { + n.label = e; + }, - YIELD$build: function(t) { - return new Node(t, YIELD); - }, + setStatement: function(n, s) { + n.statement = s; + }, - YIELD$setValue: function(n, e) { - n.value = e; + finish: function(n) { + } }, - YIELD$finish: function(n) { - }, + FUNCTION: { + build: function(t) { + var n = new Node(t); + if (n.type !== FUNCTION) + n.type = (n.value === "get") ? GETTER : SETTER; + n.params = []; + return n; + }, - GENERATOR$build: function(t) { - return new Node(t, GENERATOR); - }, + setName: function(n, v) { + n.name = v; + }, - GENERATOR$setExpression: function(n, e) { - n.expression = e; - }, + addParam: function(n, v) { + n.params.push(v); + }, - GENERATOR$setTail: function(n, n2) { - n.tail = n2; - }, + setBody: function(n, s) { + n.body = s; + }, - GENERATOR$finish: function(n) { - }, + hoistVars: function(x) { + }, - WITH$build: function(t) { - return new Node(t, WITH); + finish: function(n, x) { + } }, - WITH$setObject: function(n, e) { - n.object = e; - }, + VAR: { + build: function(t) { + return new Node(t, VAR); + }, - WITH$setBody: function(n, s) { - n.body = s; - }, + addDecl: function(n, n2, x) { + n.push(n2); + }, - WITH$finish: function(n) { + finish: function(n) { + } }, - DEBUGGER$build: function(t) { - return new Node(t, DEBUGGER); - }, + CONST: { + build: function(t) { + return new Node(t, VAR); + }, - SEMICOLON$build: function(t) { - return new Node(t, SEMICOLON); - }, + addDecl: function(n, n2, x) { + n.push(n2); + }, - SEMICOLON$setExpression: function(n, e) { - n.expression = e; + finish: function(n) { + } }, - SEMICOLON$finish: function(n) { - }, + LET: { + build: function(t) { + return new Node(t, LET); + }, - LABEL$build: function(t) { - return new Node(t, LABEL); - }, + addDecl: function(n, n2, x) { + n.push(n2); + }, - LABEL$setLabel: function(n, e) { - n.label = e; + finish: function(n) { + } }, - LABEL$setStatement: function(n, s) { - n.statement = s; - }, + DECL: { + build: function(t) { + return new Node(t, IDENTIFIER); + }, - LABEL$finish: function(n) { - }, + setName: function(n, v) { + n.name = v; + }, - FUNCTION$build: function(t) { - var n = new Node(t); - if (n.type !== FUNCTION) - n.type = (n.value === "get") ? GETTER : SETTER; - n.params = []; - return n; - }, + setInitializer: function(n, e) { + n.initializer = e; + }, - FUNCTION$setName: function(n, v) { - n.name = v; - }, + setReadOnly: function(n, b) { + n.readOnly = b; + }, - FUNCTION$addParam: function(n, v) { - n.params.push(v); + finish: function(n) { + } }, - FUNCTION$setBody: function(n, s) { - n.body = s; - }, + LET_BLOCK: { + build: function(t) { + var n = Node(t, LET_BLOCK); + n.varDecls = []; + return n; + }, - FUNCTION$hoistVars: function(x) { - }, + setVariables: function(n, n2) { + n.variables = n2; + }, - FUNCTION$finish: function(n, x) { - }, + setExpression: function(n, e) { + n.expression = e; + }, - VAR$build: function(t) { - return new Node(t, VAR); - }, + setBlock: function(n, s) { + n.block = s; + }, - VAR$addDecl: function(n, n2, x) { - n.push(n2); + finish: function(n) { + } }, - VAR$finish: function(n) { - }, + BLOCK: { + build: function(t, id) { + var n = new Node(t, BLOCK); + n.varDecls = []; + n.id = id; + return n; + }, - CONST$build: function(t) { - return new Node(t, VAR); - }, + hoistLets: function(n) { + }, - CONST$addDecl: function(n, n2, x) { - n.push(n2); - }, + addStatement: function(n, n2) { + n.push(n2); + }, - CONST$finish: function(n) { + finish: function(n) { + } }, - LET$build: function(t) { - return new Node(t, LET); - }, + EXPRESSION: { + build: function(t, tt) { + return new Node(t, tt); + }, - LET$addDecl: function(n, n2, x) { - n.push(n2); - }, + addOperand: function(n, n2) { + n.push(n2); + }, - LET$finish: function(n) { + finish: function(n) { + } }, - DECL$build: function(t) { - return new Node(t, IDENTIFIER); - }, + ASSIGN: { + build: function(t) { + return new Node(t, ASSIGN); + }, - DECL$setName: function(n, v) { - n.name = v; - }, + addOperand: function(n, n2) { + n.push(n2); + }, - DECL$setInitializer: function(n, e) { - n.initializer = e; - }, + setAssignOp: function(n, o) { + n.assignOp = o; + }, - DECL$setReadOnly: function(n, b) { - n.readOnly = b; + finish: function(n) { + } }, - DECL$finish: function(n) { - }, + HOOK: { + build: function(t) { + return new Node(t, HOOK); + }, - LET_BLOCK$build: function(t) { - var n = Node(t, LET_BLOCK); - n.varDecls = []; - return n; - }, + setCondition: function(n, e) { + n[0] = e; + }, - LET_BLOCK$setVariables: function(n, n2) { - n.variables = n2; - }, + setThenPart: function(n, n2) { + n[1] = n2; + }, - LET_BLOCK$setExpression: function(n, e) { - n.expression = e; - }, + setElsePart: function(n, n2) { + n[2] = n2; + }, - LET_BLOCK$setBlock: function(n, s) { - n.block = s; + finish: function(n) { + } }, - LET_BLOCK$finish: function(n) { - }, + OR: mkBinopBuilder(OR), + AND: mkBinopBuilder(AND), + BITWISE_OR: mkBinopBuilder(BITWISE_OR), + BITWISE_XOR: mkBinopBuilder(BITWISE_XOR), + BITWISE_AND: mkBinopBuilder(BITWISE_AND), + EQUALITY: mkBinopBuilder(), // EQ | NE | STRICT_EQ | STRICT_NE + RELATIONAL: mkBinopBuilder(), // LT | LE | GE | GT + SHIFT: mkBinopBuilder(), // LSH | RSH | URSH + ADD: mkBinopBuilder(), // PLUS | MINUS + MULTIPLY: mkBinopBuilder(), // MUL | DIV | MOD - BLOCK$build: function(t, id) { - var n = new Node(t, BLOCK); - n.varDecls = []; - n.id = id; - return n; - }, + UNARY: { + // DELETE | VOID | TYPEOF | NOT | BITWISE_NOT + // UNARY_PLUS | UNARY_MINUS | INCREMENT | DECREMENT + build: function(t) { + if (t.token.type === PLUS) + t.token.type = UNARY_PLUS; + else if (t.token.type === MINUS) + t.token.type = UNARY_MINUS; + return new Node(t); + }, - BLOCK$hoistLets: function(n) { - }, + addOperand: function(n, n2) { + n.push(n2); + }, - BLOCK$addStatement: function(n, n2) { - n.push(n2); - }, + setPostfix: function(n) { + n.postfix = true; + }, - BLOCK$finish: function(n) { + finish: function(n) { + } }, - EXPRESSION$build: function(t, tt) { - return new Node(t, tt); - }, + MEMBER: { + // NEW | DOT | INDEX + build: function(t, tt) { + return new Node(t, tt); + }, - EXPRESSION$addOperand: function(n, n2) { - n.push(n2); - }, + rebuildNewWithArgs: function(n) { + n.type = NEW_WITH_ARGS; + }, - EXPRESSION$finish: function(n) { - }, + addOperand: function(n, n2) { + n.push(n2); + }, - ASSIGN$build: function(t) { - return new Node(t, ASSIGN); + finish: function(n) { + } }, - ASSIGN$addOperand: function(n, n2) { - n.push(n2); - }, + PRIMARY: { + build: function(t, tt) { + // NB t.token.type must be NULL, THIS, TRUIE, FALSE, IDENTIFIER, + // NUMBER, STRING, or REGEXP. + return new Node(t, tt); + }, - ASSIGN$setAssignOp: function(n, o) { - n.assignOp = o; + finish: function(n) { + } }, - ASSIGN$finish: function(n) { - }, + ARRAY_INIT: { + build: function(t) { + return new Node(t, ARRAY_INIT); + }, - HOOK$build: function(t) { - return new Node(t, HOOK); - }, + addElement: function(n, n2) { + n.push(n2); + }, - HOOK$setCondition: function(n, e) { - n[0] = e; + finish: function(n) { + } }, - HOOK$setThenPart: function(n, n2) { - n[1] = n2; - }, + ARRAY_COMP: { + build: function(t) { + return new Node(t, ARRAY_COMP); + }, - HOOK$setElsePart: function(n, n2) { - n[2] = n2; - }, + setExpression: function(n, e) { + n.expression = e + }, - HOOK$finish: function(n) { - }, + setTail: function(n, n2) { + n.tail = n2; + }, - OR$build: function(t) { - return new Node(t, OR); + finish: function(n) { + } }, - OR$addOperand: function(n, n2) { - n.push(n2); - }, + COMP_TAIL: { + build: function(t) { + return new Node(t, COMP_TAIL); + }, - OR$finish: function(n) { - }, + setGuard: function(n, e) { + n.guard = e; + }, - AND$build: function(t) { - return new Node(t, AND); - }, + addFor: function(n, n2) { + n.push(n2); + }, - AND$addOperand: function(n, n2) { - n.push(n2); + finish: function(n) { + } }, - AND$finish: function(n) { - }, + OBJECT_INIT: { + build: function(t) { + return new Node(t, OBJECT_INIT); + }, - BITWISE_OR$build: function(t) { - return new Node(t, BITWISE_OR); - }, + addProperty: function(n, n2) { + n.push(n2); + }, - BITWISE_OR$addOperand: function(n, n2) { - n.push(n2); + finish: function(n) { + } }, - BITWISE_OR$finish: function(n) { - }, + PROPERTY_INIT: { + build: function(t) { + return new Node(t, PROPERTY_INIT); + }, - BITWISE_XOR$build: function(t) { - return new Node(t, BITWISE_XOR); - }, + addOperand: function(n, n2) { + n.push(n2); + }, - BITWISE_XOR$addOperand: function(n, n2) { - n.push(n2); + finish: function(n) { + } }, - BITWISE_XOR$finish: function(n) { - }, + COMMA: { + build: function(t) { + return new Node(t, COMMA); + }, - BITWISE_AND$build: function(t) { - return new Node(t, BITWISE_AND); - }, + addOperand: function(n, n2) { + n.push(n2); + }, - BITWISE_AND$addOperand: function(n, n2) { - n.push(n2); + finish: function(n) { + } }, - BITWISE_AND$finish: function(n) { - }, + LIST: { + build: function(t) { + return new Node(t, LIST); + }, - EQUALITY$build: function(t) { - // NB t.token.type must be EQ, NE, STRICT_EQ, or STRICT_NE. - return new Node(t); - }, - - EQUALITY$addOperand: function(n, n2) { - n.push(n2); - }, - - EQUALITY$finish: function(n) { - }, - - RELATIONAL$build: function(t) { - // NB t.token.type must be LT, LE, GE, or GT. - return new Node(t); - }, - - RELATIONAL$addOperand: function(n, n2) { - n.push(n2); - }, - - RELATIONAL$finish: function(n) { - }, - - SHIFT$build: function(t) { - // NB t.token.type must be LSH, RSH, or URSH. - return new Node(t); - }, - - SHIFT$addOperand: function(n, n2) { - n.push(n2); - }, - - SHIFT$finish: function(n) { - }, - - ADD$build: function(t) { - // NB t.token.type must be PLUS or MINUS. - return new Node(t); - }, - - ADD$addOperand: function(n, n2) { - n.push(n2); - }, - - ADD$finish: function(n) { - }, - - MULTIPLY$build: function(t) { - // NB t.token.type must be MUL, DIV, or MOD. - return new Node(t); - }, - - MULTIPLY$addOperand: function(n, n2) { - n.push(n2); - }, - - MULTIPLY$finish: function(n) { - }, - - UNARY$build: function(t) { - // NB t.token.type must be DELETE, VOID, TYPEOF, NOT, BITWISE_NOT, - // UNARY_PLUS, UNARY_MINUS, INCREMENT, or DECREMENT. - if (t.token.type === PLUS) - t.token.type = UNARY_PLUS; - else if (t.token.type === MINUS) - t.token.type = UNARY_MINUS; - return new Node(t); - }, - - UNARY$addOperand: function(n, n2) { - n.push(n2); - }, - - UNARY$setPostfix: function(n) { - n.postfix = true; - }, - - UNARY$finish: function(n) { - }, - - MEMBER$build: function(t, tt) { - // NB t.token.type must be NEW, DOT, or INDEX. - return new Node(t, tt); - }, - - MEMBER$rebuildNewWithArgs: function(n) { - n.type = NEW_WITH_ARGS; - }, - - MEMBER$addOperand: function(n, n2) { - n.push(n2); - }, - - MEMBER$finish: function(n) { - }, - - PRIMARY$build: function(t, tt) { - // NB t.token.type must be NULL, THIS, TRUIE, FALSE, IDENTIFIER, - // NUMBER, STRING, or REGEXP. - return new Node(t, tt); - }, - - PRIMARY$finish: function(n) { - }, - - ARRAY_INIT$build: function(t) { - return new Node(t, ARRAY_INIT); - }, - - ARRAY_INIT$addElement: function(n, n2) { - n.push(n2); - }, - - ARRAY_INIT$finish: function(n) { - }, - - ARRAY_COMP$build: function(t) { - return new Node(t, ARRAY_COMP); - }, - - ARRAY_COMP$setExpression: function(n, e) { - n.expression = e - }, - - ARRAY_COMP$setTail: function(n, n2) { - n.tail = n2; - }, - - ARRAY_COMP$finish: function(n) { - }, - - COMP_TAIL$build: function(t) { - return new Node(t, COMP_TAIL); - }, - - COMP_TAIL$setGuard: function(n, e) { - n.guard = e; - }, - - COMP_TAIL$addFor: function(n, n2) { - n.push(n2); - }, - - COMP_TAIL$finish: function(n) { - }, - - OBJECT_INIT$build: function(t) { - return new Node(t, OBJECT_INIT); - }, - - OBJECT_INIT$addProperty: function(n, n2) { - n.push(n2); - }, - - OBJECT_INIT$finish: function(n) { - }, - - PROPERTY_INIT$build: function(t) { - return new Node(t, PROPERTY_INIT); - }, - - PROPERTY_INIT$addOperand: function(n, n2) { - n.push(n2); - }, - - PROPERTY_INIT$finish: function(n) { - }, - - COMMA$build: function(t) { - return new Node(t, COMMA); - }, - - COMMA$addOperand: function(n, n2) { - n.push(n2); - }, - - COMMA$finish: function(n) { - }, - - LIST$build: function(t) { - return new Node(t, LIST); - }, - - LIST$addOperand: function(n, n2) { - n.push(n2); - }, + addOperand: function(n, n2) { + n.push(n2); + }, - LIST$finish: function(n) { + finish: function(n) { + } }, setHoists: function(id, vds) { @@ -936,16 +967,17 @@ Narcissus.parser = (function() { * For more details in its interaction with hoisting, see comments in * FunctionDefinition. */ - var b = x.builder; - var n = b.BLOCK$build(t, x.blockId++); - b.BLOCK$hoistLets(n); + var builder = x.builder; + var b = builder.BLOCK; + var n = b.build(t, x.blockId++); + b.hoistLets(n); x.stmtStack.push(n); while (!t.done && t.peek(true) !== RIGHT_CURLY) - b.BLOCK$addStatement(n, Statement(t, x)); + b.addStatement(n, Statement(t, x)); x.stmtStack.pop(); - b.BLOCK$finish(n); + b.finish(n); if (n.needsHoisting) { - b.setHoists(n.id, n.varDecls); + builder.setHoists(n.id, n.varDecls); /* * If a block needs hoisting, we need to propagate this flag up to * the CompilerContext. @@ -971,7 +1003,7 @@ Narcissus.parser = (function() { */ function Statement(t, x) { var i, label, n, n2, ss, tt = t.get(true); - var b = x.builder; + var builder = x.builder, b, b2, b3; // Cases for statements ending in a right curly return early, avoiding the // common semicolon insertion magic after this switch. @@ -989,20 +1021,24 @@ Narcissus.parser = (function() { return n; case IF: - n = b.IF$build(t); - b.IF$setCondition(n, ParenExpression(t, x)); + b = builder.IF; + n = b.build(t); + b.setCondition(n, ParenExpression(t, x)); x.stmtStack.push(n); - b.IF$setThenPart(n, Statement(t, x)); + b.setThenPart(n, Statement(t, x)); if (t.match(ELSE)) - b.IF$setElsePart(n, Statement(t, x)); + b.setElsePart(n, Statement(t, x)); x.stmtStack.pop(); - b.IF$finish(n); + b.finish(n); return n; case SWITCH: // This allows CASEs after a DEFAULT, which is in the standard. - n = b.SWITCH$build(t); - b.SWITCH$setDiscriminant(n, ParenExpression(t, x)); + b = builder.SWITCH; + b2 = builder.DEFAULT; + b3 = builder.CASE; + n = b.build(t); + b.setDiscriminant(n, ParenExpression(t, x)); x.stmtStack.push(n); t.mustMatch(LEFT_CURLY); while ((tt = t.get()) !== RIGHT_CURLY) { @@ -1010,40 +1046,41 @@ Narcissus.parser = (function() { case DEFAULT: if (n.defaultIndex >= 0) throw t.newSyntaxError("More than one switch default"); - n2 = b.DEFAULT$build(t); - b.SWITCH$setDefaultIndex(n, n.cases.length); + n2 = b2.build(t); + b.setDefaultIndex(n, n.cases.length); t.mustMatch(COLON); - b.DEFAULT$initializeStatements(n2, t); + b2.initializeStatements(n2, t); while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT && tt !== RIGHT_CURLY) - b.DEFAULT$addStatement(n2, Statement(t, x)); - b.DEFAULT$finish(n2); + b2.addStatement(n2, Statement(t, x)); + b2.finish(n2); break; case CASE: - n2 = b.CASE$build(t); - b.CASE$setLabel(n2, Expression(t, x, COLON)); + n2 = b3.build(t); + b3.setLabel(n2, Expression(t, x, COLON)); t.mustMatch(COLON); - b.CASE$initializeStatements(n2, t); + b3.initializeStatements(n2, t); while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT && tt !== RIGHT_CURLY) - b.CASE$addStatement(n2, Statement(t, x)); - b.CASE$finish(n2); + b3.addStatement(n2, Statement(t, x)); + b3.finish(n2); break; default: throw t.newSyntaxError("Invalid switch case"); } - b.SWITCH$addCase(n, n2); + b.addCase(n, n2); } x.stmtStack.pop(); - b.SWITCH$finish(n); + b.finish(n); return n; case FOR: - n = b.FOR$build(t); + b = builder.FOR; + n = b.build(t); if (t.match(IDENTIFIER) && t.token.value === "each") - b.FOR$rebuildForEach(n); + b.rebuildForEach(n); t.mustMatch(LEFT_PAREN); if ((tt = t.peek()) !== SEMICOLON) { x.inForLoopInit = true; @@ -1059,7 +1096,7 @@ Narcissus.parser = (function() { * Let in for head, we need to add an implicit block * around the rest of the for. */ - var forBlock = b.BLOCK$build(t, x.blockId++); + var forBlock = builder.BLOCK.build(t, x.blockId++); x.stmtStack.push(forBlock); n2 = Variables(t, x, forBlock); } @@ -1069,51 +1106,53 @@ Narcissus.parser = (function() { x.inForLoopInit = false; } if (n2 && t.match(IN)) { - b.FOR$rebuildForIn(n); - b.FOR$setObject(n, Expression(t, x), forBlock); + b.rebuildForIn(n); + b.setObject(n, Expression(t, x), forBlock); if (n2.type === VAR || n2.type === LET) { if (n2.length !== 1) { throw new SyntaxError("Invalid for..in left-hand side", t.filename, n2.lineno); } - b.FOR$setIterator(n, n2[0], n2, forBlock); + b.setIterator(n, n2[0], n2, forBlock); } else { - b.FOR$setIterator(n, n2, null, forBlock); + b.setIterator(n, n2, null, forBlock); } } else { - b.FOR$setSetup(n, n2); + b.setSetup(n, n2); t.mustMatch(SEMICOLON); if (n.isEach) throw t.newSyntaxError("Invalid for each..in loop"); - b.FOR$setCondition(n, (t.peek() === SEMICOLON) + b.setCondition(n, (t.peek() === SEMICOLON) ? null : Expression(t, x)); t.mustMatch(SEMICOLON); - b.FOR$setUpdate(n, (t.peek() === RIGHT_PAREN) + b.setUpdate(n, (t.peek() === RIGHT_PAREN) ? null : Expression(t, x)); } t.mustMatch(RIGHT_PAREN); - b.FOR$setBody(n, nest(t, x, n, Statement)); + b.setBody(n, nest(t, x, n, Statement)); if (forBlock) { - b.BLOCK$finish(forBlock); + builder.BLOCK.finish(forBlock); x.stmtStack.pop(); } - b.FOR$finish(n); + b.finish(n); return n; case WHILE: - n = b.WHILE$build(t); - b.WHILE$setCondition(n, ParenExpression(t, x)); - b.WHILE$setBody(n, nest(t, x, n, Statement)); - b.WHILE$finish(n); + b = builder.WHILE; + n = b.build(t); + b.setCondition(n, ParenExpression(t, x)); + b.setBody(n, nest(t, x, n, Statement)); + b.finish(n); return n; case DO: - n = b.DO$build(t); - b.DO$setBody(n, nest(t, x, n, Statement, WHILE)); - b.DO$setCondition(n, ParenExpression(t, x)); - b.DO$finish(n); + b = builder.DO; + n = b.build(t); + b.setBody(n, nest(t, x, n, Statement, WHILE)); + b.setCondition(n, ParenExpression(t, x)); + b.finish(n); if (!x.ecmaStrictMode) { //