react / react-0.13.3 / examples / basic-commonjs / node_modules / browserify / node_modules / umd / node_modules / uglify-js / lib / ast.js
80743 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 endline endcol 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 quote", {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",127quote: "[string] the original quote character"128},129}, AST_Statement);130131var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {132$documentation: "A statement consisting of an expression, i.e. a = 1 + 2",133$propdoc: {134body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"135},136_walk: function(visitor) {137return visitor._visit(this, function(){138this.body._walk(visitor);139});140}141}, AST_Statement);142143function walk_body(node, visitor) {144if (node.body instanceof AST_Statement) {145node.body._walk(visitor);146}147else node.body.forEach(function(stat){148stat._walk(visitor);149});150};151152var AST_Block = DEFNODE("Block", "body", {153$documentation: "A body of statements (usually bracketed)",154$propdoc: {155body: "[AST_Statement*] an array of statements"156},157_walk: function(visitor) {158return visitor._visit(this, function(){159walk_body(this, visitor);160});161}162}, AST_Statement);163164var AST_BlockStatement = DEFNODE("BlockStatement", null, {165$documentation: "A block statement",166}, AST_Block);167168var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {169$documentation: "The empty statement (empty block or simply a semicolon)",170_walk: function(visitor) {171return visitor._visit(this);172}173}, AST_Statement);174175var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {176$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",177$propdoc: {178body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"179},180_walk: function(visitor) {181return visitor._visit(this, function(){182this.body._walk(visitor);183});184}185}, AST_Statement);186187var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {188$documentation: "Statement with a label",189$propdoc: {190label: "[AST_Label] a label definition"191},192_walk: function(visitor) {193return visitor._visit(this, function(){194this.label._walk(visitor);195this.body._walk(visitor);196});197}198}, AST_StatementWithBody);199200var AST_IterationStatement = DEFNODE("IterationStatement", null, {201$documentation: "Internal class. All loops inherit from it."202}, AST_StatementWithBody);203204var AST_DWLoop = DEFNODE("DWLoop", "condition", {205$documentation: "Base class for do/while statements",206$propdoc: {207condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"208}209}, AST_IterationStatement);210211var AST_Do = DEFNODE("Do", null, {212$documentation: "A `do` statement",213_walk: function(visitor) {214return visitor._visit(this, function(){215this.body._walk(visitor);216this.condition._walk(visitor);217});218}219}, AST_DWLoop);220221var AST_While = DEFNODE("While", null, {222$documentation: "A `while` statement",223_walk: function(visitor) {224return visitor._visit(this, function(){225this.condition._walk(visitor);226this.body._walk(visitor);227});228}229}, AST_DWLoop);230231var AST_For = DEFNODE("For", "init condition step", {232$documentation: "A `for` statement",233$propdoc: {234init: "[AST_Node?] the `for` initialization code, or null if empty",235condition: "[AST_Node?] the `for` termination clause, or null if empty",236step: "[AST_Node?] the `for` update clause, or null if empty"237},238_walk: function(visitor) {239return visitor._visit(this, function(){240if (this.init) this.init._walk(visitor);241if (this.condition) this.condition._walk(visitor);242if (this.step) this.step._walk(visitor);243this.body._walk(visitor);244});245}246}, AST_IterationStatement);247248var AST_ForIn = DEFNODE("ForIn", "init name object", {249$documentation: "A `for ... in` statement",250$propdoc: {251init: "[AST_Node] the `for/in` initialization code",252name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",253object: "[AST_Node] the object that we're looping through"254},255_walk: function(visitor) {256return visitor._visit(this, function(){257this.init._walk(visitor);258this.object._walk(visitor);259this.body._walk(visitor);260});261}262}, AST_IterationStatement);263264var AST_With = DEFNODE("With", "expression", {265$documentation: "A `with` statement",266$propdoc: {267expression: "[AST_Node] the `with` expression"268},269_walk: function(visitor) {270return visitor._visit(this, function(){271this.expression._walk(visitor);272this.body._walk(visitor);273});274}275}, AST_StatementWithBody);276277/* -----[ scope and functions ]----- */278279var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {280$documentation: "Base class for all statements introducing a lexical scope",281$propdoc: {282directives: "[string*/S] an array of directives declared in this scope",283variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",284functions: "[Object/S] like `variables`, but only lists function declarations",285uses_with: "[boolean/S] tells whether this scope uses the `with` statement",286uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",287parent_scope: "[AST_Scope?/S] link to the parent scope",288enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",289cname: "[integer/S] current index for mangling variables (used internally by the mangler)",290},291}, AST_Block);292293var AST_Toplevel = DEFNODE("Toplevel", "globals", {294$documentation: "The toplevel scope",295$propdoc: {296globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",297},298wrap_enclose: function(arg_parameter_pairs) {299var self = this;300var args = [];301var parameters = [];302303arg_parameter_pairs.forEach(function(pair) {304var splitAt = pair.lastIndexOf(":");305306args.push(pair.substr(0, splitAt));307parameters.push(pair.substr(splitAt + 1));308});309310var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";311wrapped_tl = parse(wrapped_tl);312wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){313if (node instanceof AST_Directive && node.value == "$ORIG") {314return MAP.splice(self.body);315}316}));317return wrapped_tl;318},319wrap_commonjs: function(name, export_all) {320var self = this;321var to_export = [];322if (export_all) {323self.figure_out_scope();324self.walk(new TreeWalker(function(node){325if (node instanceof AST_SymbolDeclaration && node.definition().global) {326if (!find_if(function(n){ return n.name == node.name }, to_export))327to_export.push(node);328}329}));330}331var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";332wrapped_tl = parse(wrapped_tl);333wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){334if (node instanceof AST_SimpleStatement) {335node = node.body;336if (node instanceof AST_String) switch (node.getValue()) {337case "$ORIG":338return MAP.splice(self.body);339case "$EXPORTS":340var body = [];341to_export.forEach(function(sym){342body.push(new AST_SimpleStatement({343body: new AST_Assign({344left: new AST_Sub({345expression: new AST_SymbolRef({ name: "exports" }),346property: new AST_String({ value: sym.name }),347}),348operator: "=",349right: new AST_SymbolRef(sym),350}),351}));352});353return MAP.splice(body);354}355}356}));357return wrapped_tl;358}359}, AST_Scope);360361var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {362$documentation: "Base class for functions",363$propdoc: {364name: "[AST_SymbolDeclaration?] the name of this function",365argnames: "[AST_SymbolFunarg*] array of function arguments",366uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"367},368_walk: function(visitor) {369return visitor._visit(this, function(){370if (this.name) this.name._walk(visitor);371this.argnames.forEach(function(arg){372arg._walk(visitor);373});374walk_body(this, visitor);375});376}377}, AST_Scope);378379var AST_Accessor = DEFNODE("Accessor", null, {380$documentation: "A setter/getter function. The `name` property is always null."381}, AST_Lambda);382383var AST_Function = DEFNODE("Function", null, {384$documentation: "A function expression"385}, AST_Lambda);386387var AST_Defun = DEFNODE("Defun", null, {388$documentation: "A function definition"389}, AST_Lambda);390391/* -----[ JUMPS ]----- */392393var AST_Jump = DEFNODE("Jump", null, {394$documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"395}, AST_Statement);396397var AST_Exit = DEFNODE("Exit", "value", {398$documentation: "Base class for “exits” (`return` and `throw`)",399$propdoc: {400value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"401},402_walk: function(visitor) {403return visitor._visit(this, this.value && function(){404this.value._walk(visitor);405});406}407}, AST_Jump);408409var AST_Return = DEFNODE("Return", null, {410$documentation: "A `return` statement"411}, AST_Exit);412413var AST_Throw = DEFNODE("Throw", null, {414$documentation: "A `throw` statement"415}, AST_Exit);416417var AST_LoopControl = DEFNODE("LoopControl", "label", {418$documentation: "Base class for loop control statements (`break` and `continue`)",419$propdoc: {420label: "[AST_LabelRef?] the label, or null if none",421},422_walk: function(visitor) {423return visitor._visit(this, this.label && function(){424this.label._walk(visitor);425});426}427}, AST_Jump);428429var AST_Break = DEFNODE("Break", null, {430$documentation: "A `break` statement"431}, AST_LoopControl);432433var AST_Continue = DEFNODE("Continue", null, {434$documentation: "A `continue` statement"435}, AST_LoopControl);436437/* -----[ IF ]----- */438439var AST_If = DEFNODE("If", "condition alternative", {440$documentation: "A `if` statement",441$propdoc: {442condition: "[AST_Node] the `if` condition",443alternative: "[AST_Statement?] the `else` part, or null if not present"444},445_walk: function(visitor) {446return visitor._visit(this, function(){447this.condition._walk(visitor);448this.body._walk(visitor);449if (this.alternative) this.alternative._walk(visitor);450});451}452}, AST_StatementWithBody);453454/* -----[ SWITCH ]----- */455456var AST_Switch = DEFNODE("Switch", "expression", {457$documentation: "A `switch` statement",458$propdoc: {459expression: "[AST_Node] the `switch` “discriminant”"460},461_walk: function(visitor) {462return visitor._visit(this, function(){463this.expression._walk(visitor);464walk_body(this, visitor);465});466}467}, AST_Block);468469var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {470$documentation: "Base class for `switch` branches",471}, AST_Block);472473var AST_Default = DEFNODE("Default", null, {474$documentation: "A `default` switch branch",475}, AST_SwitchBranch);476477var AST_Case = DEFNODE("Case", "expression", {478$documentation: "A `case` switch branch",479$propdoc: {480expression: "[AST_Node] the `case` expression"481},482_walk: function(visitor) {483return visitor._visit(this, function(){484this.expression._walk(visitor);485walk_body(this, visitor);486});487}488}, AST_SwitchBranch);489490/* -----[ EXCEPTIONS ]----- */491492var AST_Try = DEFNODE("Try", "bcatch bfinally", {493$documentation: "A `try` statement",494$propdoc: {495bcatch: "[AST_Catch?] the catch block, or null if not present",496bfinally: "[AST_Finally?] the finally block, or null if not present"497},498_walk: function(visitor) {499return visitor._visit(this, function(){500walk_body(this, visitor);501if (this.bcatch) this.bcatch._walk(visitor);502if (this.bfinally) this.bfinally._walk(visitor);503});504}505}, AST_Block);506507var AST_Catch = DEFNODE("Catch", "argname", {508$documentation: "A `catch` node; only makes sense as part of a `try` statement",509$propdoc: {510argname: "[AST_SymbolCatch] symbol for the exception"511},512_walk: function(visitor) {513return visitor._visit(this, function(){514this.argname._walk(visitor);515walk_body(this, visitor);516});517}518}, AST_Block);519520var AST_Finally = DEFNODE("Finally", null, {521$documentation: "A `finally` node; only makes sense as part of a `try` statement"522}, AST_Block);523524/* -----[ VAR/CONST ]----- */525526var AST_Definitions = DEFNODE("Definitions", "definitions", {527$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",528$propdoc: {529definitions: "[AST_VarDef*] array of variable definitions"530},531_walk: function(visitor) {532return visitor._visit(this, function(){533this.definitions.forEach(function(def){534def._walk(visitor);535});536});537}538}, AST_Statement);539540var AST_Var = DEFNODE("Var", null, {541$documentation: "A `var` statement"542}, AST_Definitions);543544var AST_Const = DEFNODE("Const", null, {545$documentation: "A `const` statement"546}, AST_Definitions);547548var AST_VarDef = DEFNODE("VarDef", "name value", {549$documentation: "A variable declaration; only appears in a AST_Definitions node",550$propdoc: {551name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",552value: "[AST_Node?] initializer, or null of there's no initializer"553},554_walk: function(visitor) {555return visitor._visit(this, function(){556this.name._walk(visitor);557if (this.value) this.value._walk(visitor);558});559}560});561562/* -----[ OTHER ]----- */563564var AST_Call = DEFNODE("Call", "expression args", {565$documentation: "A function call expression",566$propdoc: {567expression: "[AST_Node] expression to invoke as function",568args: "[AST_Node*] array of arguments"569},570_walk: function(visitor) {571return visitor._visit(this, function(){572this.expression._walk(visitor);573this.args.forEach(function(arg){574arg._walk(visitor);575});576});577}578});579580var AST_New = DEFNODE("New", null, {581$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"582}, AST_Call);583584var AST_Seq = DEFNODE("Seq", "car cdr", {585$documentation: "A sequence expression (two comma-separated expressions)",586$propdoc: {587car: "[AST_Node] first element in sequence",588cdr: "[AST_Node] second element in sequence"589},590$cons: function(x, y) {591var seq = new AST_Seq(x);592seq.car = x;593seq.cdr = y;594return seq;595},596$from_array: function(array) {597if (array.length == 0) return null;598if (array.length == 1) return array[0].clone();599var list = null;600for (var i = array.length; --i >= 0;) {601list = AST_Seq.cons(array[i], list);602}603var p = list;604while (p) {605if (p.cdr && !p.cdr.cdr) {606p.cdr = p.cdr.car;607break;608}609p = p.cdr;610}611return list;612},613to_array: function() {614var p = this, a = [];615while (p) {616a.push(p.car);617if (p.cdr && !(p.cdr instanceof AST_Seq)) {618a.push(p.cdr);619break;620}621p = p.cdr;622}623return a;624},625add: function(node) {626var p = this;627while (p) {628if (!(p.cdr instanceof AST_Seq)) {629var cell = AST_Seq.cons(p.cdr, node);630return p.cdr = cell;631}632p = p.cdr;633}634},635_walk: function(visitor) {636return visitor._visit(this, function(){637this.car._walk(visitor);638if (this.cdr) this.cdr._walk(visitor);639});640}641});642643var AST_PropAccess = DEFNODE("PropAccess", "expression property", {644$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",645$propdoc: {646expression: "[AST_Node] the “container” expression",647property: "[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"648}649});650651var AST_Dot = DEFNODE("Dot", null, {652$documentation: "A dotted property access expression",653_walk: function(visitor) {654return visitor._visit(this, function(){655this.expression._walk(visitor);656});657}658}, AST_PropAccess);659660var AST_Sub = DEFNODE("Sub", null, {661$documentation: "Index-style property access, i.e. `a[\"foo\"]`",662_walk: function(visitor) {663return visitor._visit(this, function(){664this.expression._walk(visitor);665this.property._walk(visitor);666});667}668}, AST_PropAccess);669670var AST_Unary = DEFNODE("Unary", "operator expression", {671$documentation: "Base class for unary expressions",672$propdoc: {673operator: "[string] the operator",674expression: "[AST_Node] expression that this unary operator applies to"675},676_walk: function(visitor) {677return visitor._visit(this, function(){678this.expression._walk(visitor);679});680}681});682683var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {684$documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"685}, AST_Unary);686687var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {688$documentation: "Unary postfix expression, i.e. `i++`"689}, AST_Unary);690691var AST_Binary = DEFNODE("Binary", "left operator right", {692$documentation: "Binary expression, i.e. `a + b`",693$propdoc: {694left: "[AST_Node] left-hand side expression",695operator: "[string] the operator",696right: "[AST_Node] right-hand side expression"697},698_walk: function(visitor) {699return visitor._visit(this, function(){700this.left._walk(visitor);701this.right._walk(visitor);702});703}704});705706var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {707$documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",708$propdoc: {709condition: "[AST_Node]",710consequent: "[AST_Node]",711alternative: "[AST_Node]"712},713_walk: function(visitor) {714return visitor._visit(this, function(){715this.condition._walk(visitor);716this.consequent._walk(visitor);717this.alternative._walk(visitor);718});719}720});721722var AST_Assign = DEFNODE("Assign", null, {723$documentation: "An assignment expression — `a = b + 5`",724}, AST_Binary);725726/* -----[ LITERALS ]----- */727728var AST_Array = DEFNODE("Array", "elements", {729$documentation: "An array literal",730$propdoc: {731elements: "[AST_Node*] array of elements"732},733_walk: function(visitor) {734return visitor._visit(this, function(){735this.elements.forEach(function(el){736el._walk(visitor);737});738});739}740});741742var AST_Object = DEFNODE("Object", "properties", {743$documentation: "An object literal",744$propdoc: {745properties: "[AST_ObjectProperty*] array of properties"746},747_walk: function(visitor) {748return visitor._visit(this, function(){749this.properties.forEach(function(prop){750prop._walk(visitor);751});752});753}754});755756var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {757$documentation: "Base class for literal object properties",758$propdoc: {759key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.",760value: "[AST_Node] property value. For setters and getters this is an AST_Function."761},762_walk: function(visitor) {763return visitor._visit(this, function(){764this.value._walk(visitor);765});766}767});768769var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {770$documentation: "A key: value object property",771$propdoc: {772quote: "[string] the original quote character"773}774}, AST_ObjectProperty);775776var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {777$documentation: "An object setter property",778}, AST_ObjectProperty);779780var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {781$documentation: "An object getter property",782}, AST_ObjectProperty);783784var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {785$propdoc: {786name: "[string] name of this symbol",787scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",788thedef: "[SymbolDef/S] the definition of this symbol"789},790$documentation: "Base class for all symbols",791});792793var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {794$documentation: "The name of a property accessor (setter/getter function)"795}, AST_Symbol);796797var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {798$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",799$propdoc: {800init: "[AST_Node*/S] array of initializers for this declaration."801}802}, AST_Symbol);803804var AST_SymbolVar = DEFNODE("SymbolVar", null, {805$documentation: "Symbol defining a variable",806}, AST_SymbolDeclaration);807808var AST_SymbolConst = DEFNODE("SymbolConst", null, {809$documentation: "A constant declaration"810}, AST_SymbolDeclaration);811812var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {813$documentation: "Symbol naming a function argument",814}, AST_SymbolVar);815816var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {817$documentation: "Symbol defining a function",818}, AST_SymbolDeclaration);819820var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {821$documentation: "Symbol naming a function expression",822}, AST_SymbolDeclaration);823824var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {825$documentation: "Symbol naming the exception in catch",826}, AST_SymbolDeclaration);827828var AST_Label = DEFNODE("Label", "references", {829$documentation: "Symbol naming a label (declaration)",830$propdoc: {831references: "[AST_LoopControl*] a list of nodes referring to this label"832},833initialize: function() {834this.references = [];835this.thedef = this;836}837}, AST_Symbol);838839var AST_SymbolRef = DEFNODE("SymbolRef", null, {840$documentation: "Reference to some symbol (not definition/declaration)",841}, AST_Symbol);842843var AST_LabelRef = DEFNODE("LabelRef", null, {844$documentation: "Reference to a label symbol",845}, AST_Symbol);846847var AST_This = DEFNODE("This", null, {848$documentation: "The `this` symbol",849}, AST_Symbol);850851var AST_Constant = DEFNODE("Constant", null, {852$documentation: "Base class for all constants",853getValue: function() {854return this.value;855}856});857858var AST_String = DEFNODE("String", "value quote", {859$documentation: "A string literal",860$propdoc: {861value: "[string] the contents of this string",862quote: "[string] the original quote character"863}864}, AST_Constant);865866var AST_Number = DEFNODE("Number", "value", {867$documentation: "A number literal",868$propdoc: {869value: "[number] the numeric value"870}871}, AST_Constant);872873var AST_RegExp = DEFNODE("RegExp", "value", {874$documentation: "A regexp literal",875$propdoc: {876value: "[RegExp] the actual regexp"877}878}, AST_Constant);879880var AST_Atom = DEFNODE("Atom", null, {881$documentation: "Base class for atoms",882}, AST_Constant);883884var AST_Null = DEFNODE("Null", null, {885$documentation: "The `null` atom",886value: null887}, AST_Atom);888889var AST_NaN = DEFNODE("NaN", null, {890$documentation: "The impossible value",891value: 0/0892}, AST_Atom);893894var AST_Undefined = DEFNODE("Undefined", null, {895$documentation: "The `undefined` value",896value: (function(){}())897}, AST_Atom);898899var AST_Hole = DEFNODE("Hole", null, {900$documentation: "A hole in an array",901value: (function(){}())902}, AST_Atom);903904var AST_Infinity = DEFNODE("Infinity", null, {905$documentation: "The `Infinity` value",906value: 1/0907}, AST_Atom);908909var AST_Boolean = DEFNODE("Boolean", null, {910$documentation: "Base class for booleans",911}, AST_Atom);912913var AST_False = DEFNODE("False", null, {914$documentation: "The `false` atom",915value: false916}, AST_Boolean);917918var AST_True = DEFNODE("True", null, {919$documentation: "The `true` atom",920value: true921}, AST_Boolean);922923/* -----[ TreeWalker ]----- */924925function TreeWalker(callback) {926this.visit = callback;927this.stack = [];928};929TreeWalker.prototype = {930_visit: function(node, descend) {931this.stack.push(node);932var ret = this.visit(node, descend ? function(){933descend.call(node);934} : noop);935if (!ret && descend) {936descend.call(node);937}938this.stack.pop();939return ret;940},941parent: function(n) {942return this.stack[this.stack.length - 2 - (n || 0)];943},944push: function (node) {945this.stack.push(node);946},947pop: function() {948return this.stack.pop();949},950self: function() {951return this.stack[this.stack.length - 1];952},953find_parent: function(type) {954var stack = this.stack;955for (var i = stack.length; --i >= 0;) {956var x = stack[i];957if (x instanceof type) return x;958}959},960has_directive: function(type) {961return this.find_parent(AST_Scope).has_directive(type);962},963in_boolean_context: function() {964var stack = this.stack;965var i = stack.length, self = stack[--i];966while (i > 0) {967var p = stack[--i];968if ((p instanceof AST_If && p.condition === self) ||969(p instanceof AST_Conditional && p.condition === self) ||970(p instanceof AST_DWLoop && p.condition === self) ||971(p instanceof AST_For && p.condition === self) ||972(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))973{974return true;975}976if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))977return false;978self = p;979}980},981loopcontrol_target: function(label) {982var stack = this.stack;983if (label) for (var i = stack.length; --i >= 0;) {984var x = stack[i];985if (x instanceof AST_LabeledStatement && x.label.name == label.name) {986return x.body;987}988} else for (var i = stack.length; --i >= 0;) {989var x = stack[i];990if (x instanceof AST_Switch || x instanceof AST_IterationStatement)991return x;992}993}994};995996997