react / wstein / node_modules / jest-cli / node_modules / istanbul / node_modules / handlebars / node_modules / uglify-js / lib / ast.js
80713 views/***********************************************************************12A JavaScript tokenizer / parser / beautifier / compressor.3https://github.com/mishoo/UglifyJS245-------------------------------- (C) ---------------------------------67Author: Mihai Bazon8<[email protected]>9http://mihai.bazon.net/blog1011Distributed under the BSD license:1213Copyright 2012 (c) Mihai Bazon <[email protected]>1415Redistribution and use in source and binary forms, with or without16modification, are permitted provided that the following conditions17are met:1819* Redistributions of source code must retain the above20copyright notice, this list of conditions and the following21disclaimer.2223* Redistributions in binary form must reproduce the above24copyright notice, this list of conditions and the following25disclaimer in the documentation and/or other materials26provided with the distribution.2728THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY29EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR31PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE32LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,33OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,34PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR35PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY36THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR37TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF38THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF39SUCH DAMAGE.4041***********************************************************************/4243"use strict";4445function DEFNODE(type, props, methods, base) {46if (arguments.length < 4) base = AST_Node;47if (!props) props = [];48else props = props.split(/\s+/);49var self_props = props;50if (base && base.PROPS)51props = props.concat(base.PROPS);52var code = "return function AST_" + type + "(props){ if (props) { ";53for (var i = props.length; --i >= 0;) {54code += "this." + props[i] + " = props." + props[i] + ";";55}56var proto = base && new base;57if (proto && proto.initialize || (methods && methods.initialize))58code += "this.initialize();";59code += "}}";60var ctor = new Function(code)();61if (proto) {62ctor.prototype = proto;63ctor.BASE = base;64}65if (base) base.SUBCLASSES.push(ctor);66ctor.prototype.CTOR = ctor;67ctor.PROPS = props || null;68ctor.SELF_PROPS = self_props;69ctor.SUBCLASSES = [];70if (type) {71ctor.prototype.TYPE = ctor.TYPE = type;72}73if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {74if (/^\$/.test(i)) {75ctor[i.substr(1)] = methods[i];76} else {77ctor.prototype[i] = methods[i];78}79}80ctor.DEFMETHOD = function(name, method) {81this.prototype[name] = method;82};83return ctor;84};8586var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {87}, null);8889var AST_Node = DEFNODE("Node", "start end", {90clone: function() {91return new this.CTOR(this);92},93$documentation: "Base class of all AST nodes",94$propdoc: {95start: "[AST_Token] The first token of this node",96end: "[AST_Token] The last token of this node"97},98_walk: function(visitor) {99return visitor._visit(this);100},101walk: function(visitor) {102return this._walk(visitor); // not sure the indirection will be any help103}104}, null);105106AST_Node.warn_function = null;107AST_Node.warn = function(txt, props) {108if (AST_Node.warn_function)109AST_Node.warn_function(string_template(txt, props));110};111112/* -----[ statements ]----- */113114var AST_Statement = DEFNODE("Statement", null, {115$documentation: "Base class of all statements",116});117118var AST_Debugger = DEFNODE("Debugger", null, {119$documentation: "Represents a debugger statement",120}, AST_Statement);121122var AST_Directive = DEFNODE("Directive", "value scope", {123$documentation: "Represents a directive, like \"use strict\";",124$propdoc: {125value: "[string] The value of this directive as a plain string (it's not an AST_String!)",126scope: "[AST_Scope/S] The scope that this directive affects"127},128}, AST_Statement);129130var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {131$documentation: "A statement consisting of an expression, i.e. a = 1 + 2",132$propdoc: {133body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"134},135_walk: function(visitor) {136return visitor._visit(this, function(){137this.body._walk(visitor);138});139}140}, AST_Statement);141142function walk_body(node, visitor) {143if (node.body instanceof AST_Statement) {144node.body._walk(visitor);145}146else node.body.forEach(function(stat){147stat._walk(visitor);148});149};150151var AST_Block = DEFNODE("Block", "body", {152$documentation: "A body of statements (usually bracketed)",153$propdoc: {154body: "[AST_Statement*] an array of statements"155},156_walk: function(visitor) {157return visitor._visit(this, function(){158walk_body(this, visitor);159});160}161}, AST_Statement);162163var AST_BlockStatement = DEFNODE("BlockStatement", null, {164$documentation: "A block statement",165}, AST_Block);166167var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {168$documentation: "The empty statement (empty block or simply a semicolon)",169_walk: function(visitor) {170return visitor._visit(this);171}172}, AST_Statement);173174var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {175$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",176$propdoc: {177body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"178},179_walk: function(visitor) {180return visitor._visit(this, function(){181this.body._walk(visitor);182});183}184}, AST_Statement);185186var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {187$documentation: "Statement with a label",188$propdoc: {189label: "[AST_Label] a label definition"190},191_walk: function(visitor) {192return visitor._visit(this, function(){193this.label._walk(visitor);194this.body._walk(visitor);195});196}197}, AST_StatementWithBody);198199var AST_DWLoop = DEFNODE("DWLoop", "condition", {200$documentation: "Base class for do/while statements",201$propdoc: {202condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"203},204_walk: function(visitor) {205return visitor._visit(this, function(){206this.condition._walk(visitor);207this.body._walk(visitor);208});209}210}, AST_StatementWithBody);211212var AST_Do = DEFNODE("Do", null, {213$documentation: "A `do` statement",214}, AST_DWLoop);215216var AST_While = DEFNODE("While", null, {217$documentation: "A `while` statement",218}, AST_DWLoop);219220var AST_For = DEFNODE("For", "init condition step", {221$documentation: "A `for` statement",222$propdoc: {223init: "[AST_Node?] the `for` initialization code, or null if empty",224condition: "[AST_Node?] the `for` termination clause, or null if empty",225step: "[AST_Node?] the `for` update clause, or null if empty"226},227_walk: function(visitor) {228return visitor._visit(this, function(){229if (this.init) this.init._walk(visitor);230if (this.condition) this.condition._walk(visitor);231if (this.step) this.step._walk(visitor);232this.body._walk(visitor);233});234}235}, AST_StatementWithBody);236237var AST_ForIn = DEFNODE("ForIn", "init name object", {238$documentation: "A `for ... in` statement",239$propdoc: {240init: "[AST_Node] the `for/in` initialization code",241name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",242object: "[AST_Node] the object that we're looping through"243},244_walk: function(visitor) {245return visitor._visit(this, function(){246this.init._walk(visitor);247this.object._walk(visitor);248this.body._walk(visitor);249});250}251}, AST_StatementWithBody);252253var AST_With = DEFNODE("With", "expression", {254$documentation: "A `with` statement",255$propdoc: {256expression: "[AST_Node] the `with` expression"257},258_walk: function(visitor) {259return visitor._visit(this, function(){260this.expression._walk(visitor);261this.body._walk(visitor);262});263}264}, AST_StatementWithBody);265266/* -----[ scope and functions ]----- */267268var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {269$documentation: "Base class for all statements introducing a lexical scope",270$propdoc: {271directives: "[string*/S] an array of directives declared in this scope",272variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",273functions: "[Object/S] like `variables`, but only lists function declarations",274uses_with: "[boolean/S] tells whether this scope uses the `with` statement",275uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",276parent_scope: "[AST_Scope?/S] link to the parent scope",277enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",278cname: "[integer/S] current index for mangling variables (used internally by the mangler)",279},280}, AST_Block);281282var AST_Toplevel = DEFNODE("Toplevel", "globals", {283$documentation: "The toplevel scope",284$propdoc: {285globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",286},287wrap_enclose: function(arg_parameter_pairs) {288var self = this;289var args = [];290var parameters = [];291292arg_parameter_pairs.forEach(function(pair) {293var split = pair.split(":");294295args.push(split[0]);296parameters.push(split[1]);297});298299var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";300wrapped_tl = parse(wrapped_tl);301wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){302if (node instanceof AST_Directive && node.value == "$ORIG") {303return MAP.splice(self.body);304}305}));306return wrapped_tl;307},308wrap_commonjs: function(name, export_all) {309var self = this;310var to_export = [];311if (export_all) {312self.figure_out_scope();313self.walk(new TreeWalker(function(node){314if (node instanceof AST_SymbolDeclaration && node.definition().global) {315if (!find_if(function(n){ return n.name == node.name }, to_export))316to_export.push(node);317}318}));319}320var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";321wrapped_tl = parse(wrapped_tl);322wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){323if (node instanceof AST_SimpleStatement) {324node = node.body;325if (node instanceof AST_String) switch (node.getValue()) {326case "$ORIG":327return MAP.splice(self.body);328case "$EXPORTS":329var body = [];330to_export.forEach(function(sym){331body.push(new AST_SimpleStatement({332body: new AST_Assign({333left: new AST_Sub({334expression: new AST_SymbolRef({ name: "exports" }),335property: new AST_String({ value: sym.name }),336}),337operator: "=",338right: new AST_SymbolRef(sym),339}),340}));341});342return MAP.splice(body);343}344}345}));346return wrapped_tl;347}348}, AST_Scope);349350var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {351$documentation: "Base class for functions",352$propdoc: {353name: "[AST_SymbolDeclaration?] the name of this function",354argnames: "[AST_SymbolFunarg*] array of function arguments",355uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"356},357_walk: function(visitor) {358return visitor._visit(this, function(){359if (this.name) this.name._walk(visitor);360this.argnames.forEach(function(arg){361arg._walk(visitor);362});363walk_body(this, visitor);364});365}366}, AST_Scope);367368var AST_Accessor = DEFNODE("Accessor", null, {369$documentation: "A setter/getter function"370}, AST_Lambda);371372var AST_Function = DEFNODE("Function", null, {373$documentation: "A function expression"374}, AST_Lambda);375376var AST_Defun = DEFNODE("Defun", null, {377$documentation: "A function definition"378}, AST_Lambda);379380/* -----[ JUMPS ]----- */381382var AST_Jump = DEFNODE("Jump", null, {383$documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"384}, AST_Statement);385386var AST_Exit = DEFNODE("Exit", "value", {387$documentation: "Base class for “exits” (`return` and `throw`)",388$propdoc: {389value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"390},391_walk: function(visitor) {392return visitor._visit(this, this.value && function(){393this.value._walk(visitor);394});395}396}, AST_Jump);397398var AST_Return = DEFNODE("Return", null, {399$documentation: "A `return` statement"400}, AST_Exit);401402var AST_Throw = DEFNODE("Throw", null, {403$documentation: "A `throw` statement"404}, AST_Exit);405406var AST_LoopControl = DEFNODE("LoopControl", "label", {407$documentation: "Base class for loop control statements (`break` and `continue`)",408$propdoc: {409label: "[AST_LabelRef?] the label, or null if none",410},411_walk: function(visitor) {412return visitor._visit(this, this.label && function(){413this.label._walk(visitor);414});415}416}, AST_Jump);417418var AST_Break = DEFNODE("Break", null, {419$documentation: "A `break` statement"420}, AST_LoopControl);421422var AST_Continue = DEFNODE("Continue", null, {423$documentation: "A `continue` statement"424}, AST_LoopControl);425426/* -----[ IF ]----- */427428var AST_If = DEFNODE("If", "condition alternative", {429$documentation: "A `if` statement",430$propdoc: {431condition: "[AST_Node] the `if` condition",432alternative: "[AST_Statement?] the `else` part, or null if not present"433},434_walk: function(visitor) {435return visitor._visit(this, function(){436this.condition._walk(visitor);437this.body._walk(visitor);438if (this.alternative) this.alternative._walk(visitor);439});440}441}, AST_StatementWithBody);442443/* -----[ SWITCH ]----- */444445var AST_Switch = DEFNODE("Switch", "expression", {446$documentation: "A `switch` statement",447$propdoc: {448expression: "[AST_Node] the `switch` “discriminant”"449},450_walk: function(visitor) {451return visitor._visit(this, function(){452this.expression._walk(visitor);453walk_body(this, visitor);454});455}456}, AST_Block);457458var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {459$documentation: "Base class for `switch` branches",460}, AST_Block);461462var AST_Default = DEFNODE("Default", null, {463$documentation: "A `default` switch branch",464}, AST_SwitchBranch);465466var AST_Case = DEFNODE("Case", "expression", {467$documentation: "A `case` switch branch",468$propdoc: {469expression: "[AST_Node] the `case` expression"470},471_walk: function(visitor) {472return visitor._visit(this, function(){473this.expression._walk(visitor);474walk_body(this, visitor);475});476}477}, AST_SwitchBranch);478479/* -----[ EXCEPTIONS ]----- */480481var AST_Try = DEFNODE("Try", "bcatch bfinally", {482$documentation: "A `try` statement",483$propdoc: {484bcatch: "[AST_Catch?] the catch block, or null if not present",485bfinally: "[AST_Finally?] the finally block, or null if not present"486},487_walk: function(visitor) {488return visitor._visit(this, function(){489walk_body(this, visitor);490if (this.bcatch) this.bcatch._walk(visitor);491if (this.bfinally) this.bfinally._walk(visitor);492});493}494}, AST_Block);495496// XXX: this is wrong according to ECMA-262 (12.4). the catch block497// should introduce another scope, as the argname should be visible498// only inside the catch block. However, doing it this way because of499// IE which simply introduces the name in the surrounding scope. If500// we ever want to fix this then AST_Catch should inherit from501// AST_Scope.502var AST_Catch = DEFNODE("Catch", "argname", {503$documentation: "A `catch` node; only makes sense as part of a `try` statement",504$propdoc: {505argname: "[AST_SymbolCatch] symbol for the exception"506},507_walk: function(visitor) {508return visitor._visit(this, function(){509this.argname._walk(visitor);510walk_body(this, visitor);511});512}513}, AST_Block);514515var AST_Finally = DEFNODE("Finally", null, {516$documentation: "A `finally` node; only makes sense as part of a `try` statement"517}, AST_Block);518519/* -----[ VAR/CONST ]----- */520521var AST_Definitions = DEFNODE("Definitions", "definitions", {522$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",523$propdoc: {524definitions: "[AST_VarDef*] array of variable definitions"525},526_walk: function(visitor) {527return visitor._visit(this, function(){528this.definitions.forEach(function(def){529def._walk(visitor);530});531});532}533}, AST_Statement);534535var AST_Var = DEFNODE("Var", null, {536$documentation: "A `var` statement"537}, AST_Definitions);538539var AST_Const = DEFNODE("Const", null, {540$documentation: "A `const` statement"541}, AST_Definitions);542543var AST_VarDef = DEFNODE("VarDef", "name value", {544$documentation: "A variable declaration; only appears in a AST_Definitions node",545$propdoc: {546name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",547value: "[AST_Node?] initializer, or null of there's no initializer"548},549_walk: function(visitor) {550return visitor._visit(this, function(){551this.name._walk(visitor);552if (this.value) this.value._walk(visitor);553});554}555});556557/* -----[ OTHER ]----- */558559var AST_Call = DEFNODE("Call", "expression args", {560$documentation: "A function call expression",561$propdoc: {562expression: "[AST_Node] expression to invoke as function",563args: "[AST_Node*] array of arguments"564},565_walk: function(visitor) {566return visitor._visit(this, function(){567this.expression._walk(visitor);568this.args.forEach(function(arg){569arg._walk(visitor);570});571});572}573});574575var AST_New = DEFNODE("New", null, {576$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"577}, AST_Call);578579var AST_Seq = DEFNODE("Seq", "car cdr", {580$documentation: "A sequence expression (two comma-separated expressions)",581$propdoc: {582car: "[AST_Node] first element in sequence",583cdr: "[AST_Node] second element in sequence"584},585$cons: function(x, y) {586var seq = new AST_Seq(x);587seq.car = x;588seq.cdr = y;589return seq;590},591$from_array: function(array) {592if (array.length == 0) return null;593if (array.length == 1) return array[0].clone();594var list = null;595for (var i = array.length; --i >= 0;) {596list = AST_Seq.cons(array[i], list);597}598var p = list;599while (p) {600if (p.cdr && !p.cdr.cdr) {601p.cdr = p.cdr.car;602break;603}604p = p.cdr;605}606return list;607},608to_array: function() {609var p = this, a = [];610while (p) {611a.push(p.car);612if (p.cdr && !(p.cdr instanceof AST_Seq)) {613a.push(p.cdr);614break;615}616p = p.cdr;617}618return a;619},620add: function(node) {621var p = this;622while (p) {623if (!(p.cdr instanceof AST_Seq)) {624var cell = AST_Seq.cons(p.cdr, node);625return p.cdr = cell;626}627p = p.cdr;628}629},630_walk: function(visitor) {631return visitor._visit(this, function(){632this.car._walk(visitor);633if (this.cdr) this.cdr._walk(visitor);634});635}636});637638var AST_PropAccess = DEFNODE("PropAccess", "expression property", {639$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",640$propdoc: {641expression: "[AST_Node] the “container” expression",642property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"643}644});645646var AST_Dot = DEFNODE("Dot", null, {647$documentation: "A dotted property access expression",648_walk: function(visitor) {649return visitor._visit(this, function(){650this.expression._walk(visitor);651});652}653}, AST_PropAccess);654655var AST_Sub = DEFNODE("Sub", null, {656$documentation: "Index-style property access, i.e. `a[\"foo\"]`",657_walk: function(visitor) {658return visitor._visit(this, function(){659this.expression._walk(visitor);660this.property._walk(visitor);661});662}663}, AST_PropAccess);664665var AST_Unary = DEFNODE("Unary", "operator expression", {666$documentation: "Base class for unary expressions",667$propdoc: {668operator: "[string] the operator",669expression: "[AST_Node] expression that this unary operator applies to"670},671_walk: function(visitor) {672return visitor._visit(this, function(){673this.expression._walk(visitor);674});675}676});677678var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {679$documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"680}, AST_Unary);681682var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {683$documentation: "Unary postfix expression, i.e. `i++`"684}, AST_Unary);685686var AST_Binary = DEFNODE("Binary", "left operator right", {687$documentation: "Binary expression, i.e. `a + b`",688$propdoc: {689left: "[AST_Node] left-hand side expression",690operator: "[string] the operator",691right: "[AST_Node] right-hand side expression"692},693_walk: function(visitor) {694return visitor._visit(this, function(){695this.left._walk(visitor);696this.right._walk(visitor);697});698}699});700701var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {702$documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",703$propdoc: {704condition: "[AST_Node]",705consequent: "[AST_Node]",706alternative: "[AST_Node]"707},708_walk: function(visitor) {709return visitor._visit(this, function(){710this.condition._walk(visitor);711this.consequent._walk(visitor);712this.alternative._walk(visitor);713});714}715});716717var AST_Assign = DEFNODE("Assign", null, {718$documentation: "An assignment expression — `a = b + 5`",719}, AST_Binary);720721/* -----[ LITERALS ]----- */722723var AST_Array = DEFNODE("Array", "elements", {724$documentation: "An array literal",725$propdoc: {726elements: "[AST_Node*] array of elements"727},728_walk: function(visitor) {729return visitor._visit(this, function(){730this.elements.forEach(function(el){731el._walk(visitor);732});733});734}735});736737var AST_Object = DEFNODE("Object", "properties", {738$documentation: "An object literal",739$propdoc: {740properties: "[AST_ObjectProperty*] array of properties"741},742_walk: function(visitor) {743return visitor._visit(this, function(){744this.properties.forEach(function(prop){745prop._walk(visitor);746});747});748}749});750751var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {752$documentation: "Base class for literal object properties",753$propdoc: {754key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code",755value: "[AST_Node] property value. For setters and getters this is an AST_Function."756},757_walk: function(visitor) {758return visitor._visit(this, function(){759this.value._walk(visitor);760});761}762});763764var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {765$documentation: "A key: value object property",766}, AST_ObjectProperty);767768var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {769$documentation: "An object setter property",770}, AST_ObjectProperty);771772var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {773$documentation: "An object getter property",774}, AST_ObjectProperty);775776var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {777$propdoc: {778name: "[string] name of this symbol",779scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",780thedef: "[SymbolDef/S] the definition of this symbol"781},782$documentation: "Base class for all symbols",783});784785var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {786$documentation: "The name of a property accessor (setter/getter function)"787}, AST_Symbol);788789var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {790$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",791$propdoc: {792init: "[AST_Node*/S] array of initializers for this declaration."793}794}, AST_Symbol);795796var AST_SymbolVar = DEFNODE("SymbolVar", null, {797$documentation: "Symbol defining a variable",798}, AST_SymbolDeclaration);799800var AST_SymbolConst = DEFNODE("SymbolConst", null, {801$documentation: "A constant declaration"802}, AST_SymbolDeclaration);803804var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {805$documentation: "Symbol naming a function argument",806}, AST_SymbolVar);807808var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {809$documentation: "Symbol defining a function",810}, AST_SymbolDeclaration);811812var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {813$documentation: "Symbol naming a function expression",814}, AST_SymbolDeclaration);815816var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {817$documentation: "Symbol naming the exception in catch",818}, AST_SymbolDeclaration);819820var AST_Label = DEFNODE("Label", "references", {821$documentation: "Symbol naming a label (declaration)",822$propdoc: {823references: "[AST_LabelRef*] a list of nodes referring to this label"824}825}, AST_Symbol);826827var AST_SymbolRef = DEFNODE("SymbolRef", null, {828$documentation: "Reference to some symbol (not definition/declaration)",829}, AST_Symbol);830831var AST_LabelRef = DEFNODE("LabelRef", null, {832$documentation: "Reference to a label symbol",833}, AST_Symbol);834835var AST_This = DEFNODE("This", null, {836$documentation: "The `this` symbol",837}, AST_Symbol);838839var AST_Constant = DEFNODE("Constant", null, {840$documentation: "Base class for all constants",841getValue: function() {842return this.value;843}844});845846var AST_String = DEFNODE("String", "value", {847$documentation: "A string literal",848$propdoc: {849value: "[string] the contents of this string"850}851}, AST_Constant);852853var AST_Number = DEFNODE("Number", "value", {854$documentation: "A number literal",855$propdoc: {856value: "[number] the numeric value"857}858}, AST_Constant);859860var AST_RegExp = DEFNODE("RegExp", "value", {861$documentation: "A regexp literal",862$propdoc: {863value: "[RegExp] the actual regexp"864}865}, AST_Constant);866867var AST_Atom = DEFNODE("Atom", null, {868$documentation: "Base class for atoms",869}, AST_Constant);870871var AST_Null = DEFNODE("Null", null, {872$documentation: "The `null` atom",873value: null874}, AST_Atom);875876var AST_NaN = DEFNODE("NaN", null, {877$documentation: "The impossible value",878value: 0/0879}, AST_Atom);880881var AST_Undefined = DEFNODE("Undefined", null, {882$documentation: "The `undefined` value",883value: (function(){}())884}, AST_Atom);885886var AST_Hole = DEFNODE("Hole", null, {887$documentation: "A hole in an array",888value: (function(){}())889}, AST_Atom);890891var AST_Infinity = DEFNODE("Infinity", null, {892$documentation: "The `Infinity` value",893value: 1/0894}, AST_Atom);895896var AST_Boolean = DEFNODE("Boolean", null, {897$documentation: "Base class for booleans",898}, AST_Atom);899900var AST_False = DEFNODE("False", null, {901$documentation: "The `false` atom",902value: false903}, AST_Boolean);904905var AST_True = DEFNODE("True", null, {906$documentation: "The `true` atom",907value: true908}, AST_Boolean);909910/* -----[ TreeWalker ]----- */911912function TreeWalker(callback) {913this.visit = callback;914this.stack = [];915};916TreeWalker.prototype = {917_visit: function(node, descend) {918this.stack.push(node);919var ret = this.visit(node, descend ? function(){920descend.call(node);921} : noop);922if (!ret && descend) {923descend.call(node);924}925this.stack.pop();926return ret;927},928parent: function(n) {929return this.stack[this.stack.length - 2 - (n || 0)];930},931push: function (node) {932this.stack.push(node);933},934pop: function() {935return this.stack.pop();936},937self: function() {938return this.stack[this.stack.length - 1];939},940find_parent: function(type) {941var stack = this.stack;942for (var i = stack.length; --i >= 0;) {943var x = stack[i];944if (x instanceof type) return x;945}946},947in_boolean_context: function() {948var stack = this.stack;949var i = stack.length, self = stack[--i];950while (i > 0) {951var p = stack[--i];952if ((p instanceof AST_If && p.condition === self) ||953(p instanceof AST_Conditional && p.condition === self) ||954(p instanceof AST_DWLoop && p.condition === self) ||955(p instanceof AST_For && p.condition === self) ||956(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))957{958return true;959}960if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))961return false;962self = p;963}964},965loopcontrol_target: function(label) {966var stack = this.stack;967if (label) {968for (var i = stack.length; --i >= 0;) {969var x = stack[i];970if (x instanceof AST_LabeledStatement && x.label.name == label.name) {971return x.body;972}973}974} else {975for (var i = stack.length; --i >= 0;) {976var x = stack[i];977if (x instanceof AST_Switch978|| x instanceof AST_For979|| x instanceof AST_ForIn980|| x instanceof AST_DWLoop) return x;981}982}983}984};985986987