var compiler_input = "//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\nmodule TypeScript {\n export class AstLogger {\n\n constructor (public logger: ILogger) { }\n\n public logScript(script: TypeScript.Script): void {\n this.logLinemap(script.locationInfo.lineMap);\n\n var stack: AST[]= [];\n\n var pre = (cur: TypeScript.AST, parent: TypeScript.AST) => {\n stack.push(cur);\n var indent = (stack.length - 1) * 2;\n this.logComments(script, cur.preComments, indent);\n this.logNode(script, cur, indent);\n this.logComments(script, cur.postComments, indent);\n return cur;\n }\n\n var post = (cur: TypeScript.AST, parent: TypeScript.AST) => {\n stack.pop();\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(script, pre, post);\n }\n\n\n public logNode(script: TypeScript.Script, cur: TypeScript.AST, indent: number) {\n var msg = this.addPadding(\"\", indent, \"| \", true);\n\n msg = msg.concat(\"+ \" + cur.treeViewLabel());\n msg = this.addPadding(msg, 70, \" \", false);\n\n msg = msg + this.addLineColumn(script, cur.minChar);\n msg = this.addPadding(msg, 80, \" \", false);\n\n msg = msg + \"=> \";\n msg = msg + this.addLineColumn(script, cur.limChar);\n msg = this.addPadding(msg, 102, \" \", false);\n\n msg = msg.concat(\"[\" + this.addPadding(cur.minChar.toString(), 1, \" \", true) + \", \" + this.addPadding(cur.limChar.toString(), 1, \" \", true) + \"]\");\n\n msg = this.addPadding(msg, 115, \" \", false);\n msg = msg.concat(\"sym=\" + (cur).sym);\n\n msg = this.addPadding(msg, 135, \" \", false);\n msg = msg.concat(\"type=\" + (cur.type === null ? \"null\" : cur.type.getTypeName()));\n this.logger.log(msg);\n }\n\n private logComments(script: TypeScript.Script, comments: TypeScript.AST[], indent: number) {\n if (comments == null)\n return;\n\n for (var i = 0; i < comments.length; i++) {\n this.logNode(script, comments[i], indent);\n }\n }\n\n public logLinemap(linemap: number[]) {\n var result = \"[\";\n for (var i = 0; i < linemap.length; i++) {\n if (i > 0)\n result += \",\";\n result += linemap[i];\n }\n result += \"]\";\n this.logger.log(\"linemap: \" + result);\n }\n\n private addPadding(s: string, targetLength: number, paddingString: string, leftPadding: bool): string {\n var result = (leftPadding ? \"\" : s);\n for (var i = s.length; i < targetLength; i++) {\n result = result + paddingString;\n }\n result = result + (leftPadding ? s : \"\");\n return result;\n }\n\n private addLineColumn(script: TypeScript.Script, position: number): string {\n // just for calling getSourceLineColFromMap\n var lineInfo = {\n line: -1,\n col: -1\n }\n TypeScript.getSourceLineColFromMap(lineInfo, position, script.locationInfo.lineMap);\n\n if (lineInfo.col !== -1) {\n lineInfo.col++; //TODO: function above seems to consider line as 1-based, and column as 0-based\n }\n\n return \"(\" + lineInfo.line + \", \" + lineInfo.col + \")\";\n }\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///\n\nmodule TypeScript {\n export function lastOf(items: any[]): any {\n return (items === null || items.length === 0) ? null : items[items.length - 1];\n }\n\n export function max(a: number, b: number): number {\n return a >= b ? a : b;\n }\n\n export function min(a: number, b: number): number {\n return a <= b ? a : b;\n }\n\n //\n // Helper class representing a path from a root ast node to a (grand)child ast node.\n // This is helpful as our tree don't have parents.\n //\n export class AstPath {\n public asts: TypeScript.AST[] = [];\n public top: number = -1;\n\n static reverseIndexOf(items: any[], index: number): any {\n return (items === null || items.length <= index) ? null : items[items.length - index - 1];\n }\n\n public clone(): AstPath {\n var clone = new AstPath();\n clone.asts = this.asts.map((value) => { return value; });\n clone.top = this.top;\n return clone;\n }\n\n public pop(): TypeScript.AST {\n var head = this.ast();\n this.up();\n\n while (this.asts.length > this.count()) {\n this.asts.pop();\n }\n return head;\n }\n\n public push(ast: TypeScript.AST) {\n while (this.asts.length > this.count()) {\n this.asts.pop();\n }\n this.top = this.asts.length;\n this.asts.push(ast);\n }\n\n public up() {\n if (this.top <= -1)\n throw new Error(\"Invalid call to 'up'\");\n this.top--;\n }\n\n public down() {\n if (this.top == this.ast.length - 1)\n throw new Error(\"Invalid call to 'down'\");\n this.top++;\n }\n\n public nodeType(): TypeScript.NodeType {\n if (this.ast() == null)\n return TypeScript.NodeType.None;\n return this.ast().nodeType;\n }\n\n public ast() {\n return AstPath.reverseIndexOf(this.asts, this.asts.length - (this.top + 1));\n }\n\n public parent() {\n return AstPath.reverseIndexOf(this.asts, this.asts.length - this.top);\n }\n\n public count() {\n return this.top + 1;\n }\n\n public get(index: number): TypeScript.AST {\n return this.asts[index];\n }\n\n public isNameOfClass(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.ClassDeclaration) &&\n ((this.parent()).name === this.ast());\n }\n\n public isNameOfInterface(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.InterfaceDeclaration) &&\n ((this.parent()).name === this.ast());\n }\n\n public isNameOfArgument(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.ArgDecl) &&\n ((this.parent()).id === this.ast());\n }\n\n public isNameOfVariable(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.VarDecl) &&\n ((this.parent()).id === this.ast());\n }\n\n public isNameOfModule(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.ModuleDeclaration) &&\n ((this.parent()).name === this.ast());\n }\n\n public isNameOfFunction(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.FuncDecl) &&\n ((this.parent()).name === this.ast());\n }\n\n public isChildOfScript(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.Script;\n }\n\n public isChildOfModule(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.ModuleDeclaration;\n }\n\n public isChildOfClass(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.ClassDeclaration;\n }\n\n public isArgumentOfClassConstructor(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 5 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl &&\n this.asts[this.top - 3].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 4].nodeType === TypeScript.NodeType.ClassDeclaration &&\n ((this.asts[this.top - 2]).isConstructor) &&\n ((this.asts[this.top - 2]).arguments === this.asts[this.top - 1]) &&\n ((this.asts[this.top - 4]).constructorDecl === this.asts[this.top - 2]);\n }\n\n public isChildOfInterface(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.InterfaceDeclaration;\n }\n\n public isTopLevelImplicitModule() {\n return this.count() >= 1 &&\n this.asts[this.top].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n TypeScript.hasFlag((this.asts[this.top]).modFlags, TypeScript.ModuleFlags.IsWholeFile);\n }\n\n public isBodyOfTopLevelImplicitModule() {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n (this.asts[this.top - 1]).members == this.asts[this.top - 0] &&\n TypeScript.hasFlag((this.asts[this.top - 1]).modFlags, TypeScript.ModuleFlags.IsWholeFile);\n }\n\n public isBodyOfScript(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Script &&\n (this.asts[this.top - 1]).bod == this.asts[this.top - 0];\n }\n\n public isBodyOfSwitch(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Switch &&\n (this.asts[this.top - 1]).caseList == this.asts[this.top - 0];\n }\n\n public isBodyOfModule(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n (this.asts[this.top - 1]).members == this.asts[this.top - 0];\n }\n\n public isBodyOfClass(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ClassDeclaration &&\n (this.asts[this.top - 1]).members == this.asts[this.top - 0];\n }\n\n public isBodyOfFunction(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl &&\n (this.asts[this.top - 1]).bod == this.asts[this.top - 0];\n }\n\n public isBodyOfInterface(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.InterfaceDeclaration &&\n (this.asts[this.top - 1]).members == this.asts[this.top - 0];\n }\n\n public isBodyOfBlock(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Block &&\n (this.asts[this.top - 1]).statements == this.asts[this.top - 0];\n }\n\n public isBodyOfFor(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.For &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfCase(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Case &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfTry(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Try &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfCatch(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Catch &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfDoWhile(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.DoWhile &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfWhile(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.While &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfForIn(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ForIn &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfWith(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.With &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfFinally(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Finally &&\n (this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isCaseOfSwitch(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n (this.asts[this.top - 2]).caseList == this.asts[this.top - 1];\n }\n\n public isDefaultCaseOfSwitch(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n (this.asts[this.top - 2]).caseList == this.asts[this.top - 1] &&\n (this.asts[this.top - 2]).defaultCase == this.asts[this.top - 0];\n }\n\n public isListOfObjectLit(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n (this.asts[this.top - 1]).operand == this.asts[this.top - 0];\n }\n\n public isBodyOfObjectLit(): bool {\n return this.isListOfObjectLit();\n }\n\n public isEmptyListOfObjectLit(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n (this.asts[this.top - 1]).operand == this.asts[this.top - 0] &&\n (this.asts[this.top - 0]).members.length == 0;\n }\n\n public isMemberOfObjectLit(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.Member &&\n (this.asts[this.top - 2]).operand == this.asts[this.top - 1];\n }\n\n public isNameOfMemberOfObjectLit(): bool {\n return this.count() >= 4 &&\n this.asts[this.top - 3].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.Name &&\n (this.asts[this.top - 3]).operand == this.asts[this.top - 2];\n }\n\n public isListOfArrayLit(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ArrayLit &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n (this.asts[this.top - 1]).operand == this.asts[this.top - 0];\n }\n\n public isTargetOfMember(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n (this.asts[this.top - 1]).operand1 === this.asts[this.top - 0];\n }\n\n public isMemberOfMember(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n (this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];\n }\n\n public isItemOfList(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List;\n //(this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];\n }\n\n public isThenOfIf(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.If &&\n (this.asts[this.top - 1]).thenBod == this.asts[this.top - 0];\n }\n\n public isElseOfIf(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.If &&\n (this.asts[this.top - 1]).elseBod == this.asts[this.top - 0];\n }\n\n public isBodyOfDefaultCase(): bool {\n return this.isBodyOfCase();\n }\n\n public isSingleStatementList(): bool {\n return this.count() >= 1 &&\n this.asts[this.top].nodeType === TypeScript.NodeType.List &&\n (this.asts[this.top]).members.length === 1;\n }\n\n public isArgumentListOfFunction(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl &&\n (this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n }\n\n public isArgumentOfFunction(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl &&\n (this.asts[this.top - 2]).arguments === this.asts[this.top - 1];\n }\n\n public isArgumentListOfCall(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Call &&\n (this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n }\n\n public isArgumentListOfNew(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.New &&\n (this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n }\n\n public isSynthesizedBlock(): bool {\n return this.count() >= 1 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.Block &&\n (this.asts[this.top - 0]).isStatementBlock === false;\n }\n }\n\n export function isValidAstNode(ast: TypeScript.ASTSpan): bool {\n if (ast === null)\n return false;\n\n if (ast.minChar === -1 || ast.limChar === -1)\n return false;\n\n return true;\n }\n\n export class AstPathContext {\n public path = new TypeScript.AstPath();\n }\n\n export enum GetAstPathOptions {\n Default = 0,\n EdgeInclusive = 1,\n //We need this options dealing with an AST coming from an incomplete AST. For example:\n // class foo { // r\n // If we ask for the AST at the position after the \"r\" character, we won't see we are \n // inside a comment, because the \"class\" AST node has a limChar corresponding to the position of \n // the \"{\" character, meaning we don't traverse the tree down to the stmt list of the class, meaning\n // we don't find the \"precomment\" attached to the errorneous empty stmt.\n //TODO: It would be nice to be able to get rid of this.\n DontPruneSearchBasedOnPosition = 1 << 1,\n }\n\n ///\n /// Return the stack of AST nodes containing \"position\"\n ///\n export function getAstPathToPosition(script: TypeScript.AST, pos: number, options = GetAstPathOptions.Default): TypeScript.AstPath {\n var lookInComments = (comments: TypeScript.Comment[]) => {\n if (comments && comments.length > 0) {\n for (var i = 0; i < comments.length; i++) {\n var minChar = comments[i].minChar;\n var limChar = comments[i].limChar;\n if (!comments[i].isBlockComment) {\n limChar++; // For single line comments, include 1 more character (for the newline)\n }\n if (pos >= minChar && pos < limChar) {\n ctx.path.push(comments[i]);\n }\n }\n }\n }\n\n var pre = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: IAstWalker) {\n if (isValidAstNode(cur)) {\n\n // Add \"cur\" to the stack if it contains our position\n // For \"identifier\" nodes, we need a special case: A position equal to \"limChar\" is\n // valid, since the position corresponds to a caret position (in between characters)\n // For example:\n // bar\n // 0123\n // If \"position == 3\", the caret is at the \"right\" of the \"r\" character, which should be considered valid\n var inclusive =\n hasFlag(options, GetAstPathOptions.EdgeInclusive) ||\n cur.nodeType === TypeScript.NodeType.Name ||\n pos === script.limChar; // Special \"EOF\" case\n\n var minChar = cur.minChar;\n var limChar = cur.limChar + (inclusive ? 1 : 0)\n if (pos >= minChar && pos < limChar) {\n\n // TODO: Since AST is sometimes not correct wrt to position, only add \"cur\" if it's better\n // than top of the stack.\n var previous = ctx.path.ast();\n if (previous == null || (cur.minChar >= previous.minChar && cur.limChar <= previous.limChar)) {\n ctx.path.push(cur);\n }\n else {\n //logger.log(\"TODO: Ignoring node because minChar, limChar not better than previous node in stack\");\n }\n }\n\n // The AST walker skips comments, but we might be in one, so check the pre/post comments for this node manually\n if (pos < limChar) {\n lookInComments(cur.preComments);\n }\n if (pos >= minChar) {\n lookInComments(cur.postComments);\n }\n\n if (!hasFlag(options, GetAstPathOptions.DontPruneSearchBasedOnPosition)) {\n // Don't go further down the tree if pos is outside of [minChar, limChar]\n walker.options.goChildren = (minChar <= pos && pos <= limChar);\n }\n }\n return cur;\n }\n\n var ctx = new AstPathContext();\n TypeScript.getAstWalkerFactory().walk(script, pre, null, null, ctx);\n return ctx.path;\n }\n\n //\n // Find a source text offset that is safe for lexing tokens at the given position.\n // This is used when \"position\" might be inside a comment or string, etc.\n //\n export function getTokenizationOffset(script: TypeScript.Script, position: number): number {\n var bestOffset = 0;\n var pre = (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker): TypeScript.AST => {\n if (TypeScript.isValidAstNode(cur)) {\n // Did we find a closer offset?\n if (cur.minChar <= position) {\n bestOffset = max(bestOffset, cur.minChar);\n }\n\n // Stop the walk if this node is not related to \"minChar\"\n if (cur.minChar > position || cur.limChar < bestOffset) {\n walker.options.goChildren = false;\n }\n }\n\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(script, pre);\n return bestOffset;\n }\n\n ///\n /// Simple function to Walk an AST using a simple callback function.\n ///\n export function walkAST(ast: TypeScript.AST, callback: (path: AstPath, walker: TypeScript.IAstWalker) => void ): void {\n var pre = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n var path: TypeScript.AstPath = walker.state;\n path.push(cur);\n callback(path, walker);\n return cur;\n }\n var post = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n var path: TypeScript.AstPath = walker.state;\n path.pop();\n return cur;\n }\n\n var path = new AstPath();\n TypeScript.getAstWalkerFactory().walk(ast, pre, post, null, path);\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///\n\nmodule TypeScript {\n export class ASTSpan {\n public minChar: number = -1; // -1 = \"undefined\" or \"compiler generated\"\n public limChar: number = -1; // -1 = \"undefined\" or \"compiler generated\" \n }\n\n export class AST extends ASTSpan {\n public type: Type = null;\n public flags = ASTFlags.Writeable;\n\n // REVIEW: for diagnostic purposes\n public passCreated: number = CompilerDiagnostics.analysisPass;\n\n public preComments: Comment[] = null;\n public postComments: Comment[] = null;\n private docComments: Comment[] = null;\n\n public isParenthesized = false;\n\n constructor (public nodeType: NodeType) {\n super();\n }\n\n public isExpression() { return false; }\n\n public isStatementOrExpression() { return false; }\n\n public isCompoundStatement() { return false; }\n\n public isLeaf() { return this.isStatementOrExpression() && (!this.isCompoundStatement()); }\n \n public isDeclaration() { return false; }\n\n public typeCheck(typeFlow: TypeFlow) {\n switch (this.nodeType) {\n case NodeType.Error:\n case NodeType.EmptyExpr:\n this.type = typeFlow.anyType;\n break;\n case NodeType.This:\n return typeFlow.typeCheckThis(this);\n case NodeType.Null:\n this.type = typeFlow.nullType;\n break;\n case NodeType.False:\n case NodeType.True:\n this.type = typeFlow.booleanType;\n break;\n case NodeType.Super:\n return typeFlow.typeCheckSuper(this);\n case NodeType.EndCode:\n case NodeType.Empty:\n case NodeType.Void:\n this.type = typeFlow.voidType;\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n switch (this.nodeType) {\n case NodeType.This:\n emitter.recordSourceMappingStart(this);\n if (emitter.thisFnc && (hasFlag(emitter.thisFnc.fncFlags, FncFlags.IsFatArrowFunction))) {\n emitter.writeToOutput(\"_this\");\n }\n else {\n emitter.writeToOutput(\"this\");\n }\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.Null:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"null\");\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.False:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"false\");\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.True:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"true\");\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.Super:\n emitter.recordSourceMappingStart(this);\n emitter.emitSuperReference();\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.EndCode:\n case NodeType.Error:\n case NodeType.EmptyExpr:\n break;\n case NodeType.Empty:\n emitter.recordSourceMappingStart(this);\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.Void:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"void \");\n emitter.recordSourceMappingEnd(this);\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public print(context: PrintContext) {\n context.startLine();\n var lineCol = { line: -1, col: -1 };\n var limLineCol = { line: -1, col: -1 };\n if (context.parser !== null) {\n context.parser.getSourceLineCol(lineCol, this.minChar);\n context.parser.getSourceLineCol(limLineCol, this.limChar);\n context.write(\"(\" + lineCol.line + \",\" + lineCol.col + \")--\" +\n \"(\" + limLineCol.line + \",\" + limLineCol.col + \"): \");\n }\n var lab = this.printLabel();\n if (hasFlag(this.flags, ASTFlags.Error)) {\n lab += \" (Error)\";\n }\n context.writeLine(lab);\n }\n\n public printLabel() {\n if (nodeTypeTable[this.nodeType] !== undefined) {\n return nodeTypeTable[this.nodeType];\n }\n else {\n return (NodeType)._map[this.nodeType];\n }\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n // by default, AST adds itself to current basic block and does not check its children\n context.walker.options.goChildren = false;\n context.addContent(this);\n }\n\n public netFreeUses(container: Symbol, freeUses: StringHashTable) {\n }\n\n public treeViewLabel() {\n return (NodeType)._map[this.nodeType];\n }\n\n public static getResolvedIdentifierName(name: string): string {\n if (!name) return \"\";\n\n var resolved = \"\";\n var start = 0;\n var i = 0;\n while(i <= name.length - 6) {\n // Look for escape sequence \\uxxxx\n if (name.charAt(i) == '\\\\' && name.charAt(i+1) == 'u') {\n var charCode = parseInt(name.substr(i + 2, 4), 16);\n resolved += name.substr(start, i - start);\n resolved += String.fromCharCode(charCode);\n i += 6;\n start = i;\n continue;\n } \n i++;\n }\n // Append remaining string\n resolved += name.substring(start);\n return resolved;\n }\n\n public getDocComments() : Comment[] {\n if (!this.isDeclaration() || !this.preComments || this.preComments.length == 0) {\n return [];\n }\n\n if (!this.docComments) {\n var preCommentsLength = this.preComments.length;\n var docComments: Comment[] = [];\n for (var i = preCommentsLength - 1; i >= 0; i--) {\n if (this.preComments[i].isDocComment()) {\n var prevDocComment = docComments.length > 0 ? docComments[docComments.length - 1] : null;\n if (prevDocComment == null || // If the help comments were not yet set then this is the comment\n (this.preComments[i].limLine == prevDocComment.minLine ||\n this.preComments[i].limLine + 1 == prevDocComment.minLine)) { // On same line or next line\n docComments.push(this.preComments[i]);\n continue;\n }\n }\n break;\n }\n\n this.docComments = docComments.reverse();\n }\n\n return this.docComments;\n }\n }\n\n export class IncompleteAST extends AST {\n constructor (min: number, lim: number) {\n super(NodeType.Error);\n\n this.minChar = min;\n this.limChar = lim;\n }\n }\n\n export class ASTList extends AST {\n public enclosingScope: SymbolScope = null;\n public members: AST[] = new AST[];\n\n constructor () {\n super(NodeType.List);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var len = this.members.length;\n for (var i = 0; i < len; i++) {\n if (context.noContinuation) {\n context.addUnreachable(this.members[i]);\n break;\n }\n else {\n this.members[i] = context.walk(this.members[i], this);\n }\n }\n context.walker.options.goChildren = false;\n }\n\n public append(ast: AST) {\n this.members[this.members.length] = ast;\n return this;\n }\n\n public appendAll(ast: AST) {\n if (ast.nodeType == NodeType.List) {\n var list = ast;\n for (var i = 0, len = list.members.length; i < len; i++) {\n this.append(list.members[i]);\n }\n }\n else {\n this.append(ast);\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascriptList(this, null, TokenID.Semicolon, startLine, false, false);\n emitter.recordSourceMappingEnd(this);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var len = this.members.length;\n typeFlow.nestingLevel++;\n for (var i = 0; i < len; i++) {\n if (this.members[i]) {\n this.members[i] = this.members[i].typeCheck(typeFlow);\n }\n }\n typeFlow.nestingLevel--;\n return this;\n }\n }\n\n export class Identifier extends AST {\n public sym: Symbol = null;\n public cloId = -1;\n public text: string;\n\n // 'actualText' is the text that the user has entered for the identifier. the text might \n // include any Unicode escape sequences (e.g.: \\u0041 for 'A'). 'text', however, contains \n // the resolved value of any escape sequences in the actual text; so in the previous \n // example, actualText = '\\u0041', text = 'A'.\n //\n // For purposes of finding a symbol, use text, as this will allow you to match all \n // variations of the variable text. For full-fidelity translation of the user input, such\n // as emitting, use the actualText field.\n // \n // Note: \n // To change text, and to avoid running into a situation where 'actualText' does not \n // match 'text', always use setText.\n constructor (public actualText: string, public hasEscapeSequence?: bool) {\n super(NodeType.Name);\n this.setText(actualText, hasEscapeSequence);\n }\n\n public setText(actualText: string, hasEscapeSequence?: bool) {\n this.actualText = actualText;\n if (hasEscapeSequence) {\n this.text = AST.getResolvedIdentifierName(actualText);\n }\n else {\n this.text = actualText;\n }\n }\n\n public isMissing() { return false; }\n public isLeaf() { return true; }\n\n public treeViewLabel() {\n return \"id: \" + this.actualText;\n }\n\n public printLabel() {\n if (this.actualText) {\n return \"id: \" + this.actualText;\n }\n else {\n return \"name node\";\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckName(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptName(this, true);\n }\n\n public static fromToken(token: Token): Identifier {\n return new Identifier(token.getText(), (token).hasEscapeSequence);\n }\n }\n\n export class MissingIdentifier extends Identifier {\n constructor () {\n super(\"__missing\");\n }\n\n public isMissing() {\n return true;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n // Emit nothing for a missing ID\n }\n }\n\n export class Label extends AST {\n constructor (public id: Identifier) {\n super(NodeType.Label);\n }\n\n public printLabel() { return this.id.actualText + \":\"; }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.voidType;\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.recordSourceMappingStart(this.id);\n emitter.writeToOutput(this.id.actualText);\n emitter.recordSourceMappingEnd(this.id);\n emitter.writeLineToOutput(\":\");\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class Expression extends AST {\n constructor (nodeType: NodeType) {\n super(nodeType);\n }\n\n public isExpression() { return true; }\n\n public isStatementOrExpression() { return true; }\n }\n\n export class UnaryExpression extends Expression {\n public targetType: Type = null; // Target type for an object literal (null if no target type)\n public castTerm: AST = null;\n\n constructor (nodeType: NodeType, public operand: AST) {\n super(nodeType);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n super.addToControlFlow(context);\n // TODO: add successor as catch block/finally block if present\n if (this.nodeType == NodeType.Throw) {\n context.returnStmt();\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n switch (this.nodeType) {\n case NodeType.Not:\n return typeFlow.typeCheckBitNot(this);\n\n case NodeType.LogNot:\n return typeFlow.typeCheckLogNot(this);\n\n case NodeType.Pos:\n case NodeType.Neg:\n return typeFlow.typeCheckUnaryNumberOperator(this);\n\n case NodeType.IncPost:\n case NodeType.IncPre:\n case NodeType.DecPost:\n case NodeType.DecPre:\n return typeFlow.typeCheckIncOrDec(this);\n\n case NodeType.ArrayLit:\n typeFlow.typeCheckArrayLit(this);\n return this;\n\n case NodeType.ObjectLit:\n typeFlow.typeCheckObjectLit(this);\n return this;\n\n case NodeType.Throw:\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.voidType;\n return this;\n\n case NodeType.Typeof:\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.stringType;\n return this;\n\n case NodeType.Delete:\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.booleanType;\n break;\n\n case NodeType.TypeAssertion:\n this.castTerm = typeFlow.typeCheck(this.castTerm);\n var applyTargetType = !this.operand.isParenthesized;\n\n var targetType = applyTargetType ? this.castTerm.type : null;\n\n typeFlow.checker.typeCheckWithContextualType(targetType, typeFlow.checker.inProvisionalTypecheckMode(), true, this.operand);\n typeFlow.castWithCoercion(this.operand, this.castTerm.type, false, true);\n this.type = this.castTerm.type;\n return this;\n\n case NodeType.Void:\n // REVIEW - Although this is good to do for completeness's sake,\n // this shouldn't be strictly necessary from the void operator's\n // point of view\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.checker.undefinedType;\n break;\n\n default:\n throw new Error(\"please implement in derived class\");\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n switch (this.nodeType) {\n case NodeType.IncPost:\n emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);\n emitter.writeToOutput(\"++\");\n break;\n case NodeType.LogNot:\n emitter.writeToOutput(\"!\");\n emitter.emitJavascript(this.operand, TokenID.Exclamation, false);\n break;\n case NodeType.DecPost:\n emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);\n emitter.writeToOutput(\"--\");\n break;\n case NodeType.ObjectLit:\n emitter.emitObjectLiteral(this.operand);\n break;\n case NodeType.ArrayLit:\n emitter.emitArrayLiteral(this.operand);\n break;\n case NodeType.Not:\n emitter.writeToOutput(\"~\");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.Neg:\n emitter.writeToOutput(\"-\");\n if (this.operand.nodeType == NodeType.Neg) {\n this.operand.isParenthesized = true;\n }\n emitter.emitJavascript(this.operand, TokenID.Minus, false);\n break;\n case NodeType.Pos:\n emitter.writeToOutput(\"+\");\n if (this.operand.nodeType == NodeType.Pos) {\n this.operand.isParenthesized = true;\n }\n emitter.emitJavascript(this.operand, TokenID.Plus, false);\n break;\n case NodeType.IncPre:\n emitter.writeToOutput(\"++\");\n emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);\n break;\n case NodeType.DecPre:\n emitter.writeToOutput(\"--\");\n emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);\n break;\n case NodeType.Throw:\n emitter.writeToOutput(\"throw \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n emitter.writeToOutput(\";\");\n break;\n case NodeType.Typeof:\n emitter.writeToOutput(\"typeof \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.Delete:\n emitter.writeToOutput(\"delete \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.Void:\n emitter.writeToOutput(\"void \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.TypeAssertion:\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class CallExpression extends Expression {\n constructor (nodeType: NodeType,\n public target: AST,\n public arguments: ASTList) {\n super(nodeType);\n this.minChar = this.target.minChar;\n }\n\n public signature: Signature = null;\n\n public typeCheck(typeFlow: TypeFlow) {\n if (this.nodeType == NodeType.New) {\n return typeFlow.typeCheckNew(this);\n }\n else {\n return typeFlow.typeCheckCall(this);\n }\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n\n if (this.nodeType == NodeType.New) {\n emitter.emitNew(this.target, this.arguments);\n }\n else {\n emitter.emitCall(this, this.target, this.arguments);\n }\n\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class BinaryExpression extends Expression {\n constructor (nodeType: NodeType, public operand1: AST, public operand2: AST) {\n super(nodeType);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n switch (this.nodeType) {\n case NodeType.Dot:\n return typeFlow.typeCheckDotOperator(this);\n case NodeType.Asg:\n return typeFlow.typeCheckAsgOperator(this);\n case NodeType.Add:\n case NodeType.Sub:\n case NodeType.Mul:\n case NodeType.Div:\n case NodeType.Mod:\n case NodeType.Or:\n case NodeType.And:\n return typeFlow.typeCheckArithmeticOperator(this, false);\n case NodeType.Xor:\n return typeFlow.typeCheckBitwiseOperator(this, false);\n case NodeType.Ne:\n case NodeType.Eq:\n var text: string;\n if (typeFlow.checker.styleSettings.eqeqeq) {\n text = nodeTypeTable[this.nodeType];\n typeFlow.checker.errorReporter.styleError(this, \"use of \" + text);\n }\n else if (typeFlow.checker.styleSettings.eqnull) {\n text = nodeTypeTable[this.nodeType];\n if ((this.operand2 !== null) && (this.operand2.nodeType == NodeType.Null)) {\n typeFlow.checker.errorReporter.styleError(this, \"use of \" + text + \" to compare with null\");\n }\n }\n case NodeType.Eqv:\n case NodeType.NEqv:\n case NodeType.Lt:\n case NodeType.Le:\n case NodeType.Ge:\n case NodeType.Gt:\n return typeFlow.typeCheckBooleanOperator(this);\n case NodeType.Index:\n return typeFlow.typeCheckIndex(this);\n case NodeType.Member:\n this.type = typeFlow.voidType;\n return this;\n case NodeType.LogOr:\n return typeFlow.typeCheckLogOr(this);\n case NodeType.LogAnd:\n return typeFlow.typeCheckLogAnd(this);\n case NodeType.AsgAdd:\n case NodeType.AsgSub:\n case NodeType.AsgMul:\n case NodeType.AsgDiv:\n case NodeType.AsgMod:\n case NodeType.AsgOr:\n case NodeType.AsgAnd:\n return typeFlow.typeCheckArithmeticOperator(this, true);\n case NodeType.AsgXor:\n return typeFlow.typeCheckBitwiseOperator(this, true);\n case NodeType.Lsh:\n case NodeType.Rsh:\n case NodeType.Rs2:\n return typeFlow.typeCheckShift(this, false);\n case NodeType.AsgLsh:\n case NodeType.AsgRsh:\n case NodeType.AsgRs2:\n return typeFlow.typeCheckShift(this, true);\n case NodeType.Comma:\n return typeFlow.typeCheckCommaOperator(this);\n case NodeType.InstOf:\n return typeFlow.typeCheckInstOf(this);\n case NodeType.In:\n return typeFlow.typeCheckInOperator(this);\n case NodeType.From:\n typeFlow.checker.errorReporter.simpleError(this, \"Illegal use of 'from' keyword in binary expression\");\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n var binTokenId = nodeTypeToTokTable[this.nodeType];\n\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (binTokenId != undefined) {\n\n emitter.emitJavascript(this.operand1, binTokenId, false);\n\n if (tokenTable[binTokenId].text == \"instanceof\") {\n emitter.writeToOutput(\" instanceof \");\n }\n else if (tokenTable[binTokenId].text == \"in\") {\n emitter.writeToOutput(\" in \");\n }\n else {\n emitter.writeToOutputTrimmable(\" \" + tokenTable[binTokenId].text + \" \");\n }\n\n emitter.emitJavascript(this.operand2, binTokenId, false);\n }\n else {\n switch (this.nodeType) {\n case NodeType.Dot:\n if (!emitter.tryEmitConstant(this)) {\n emitter.emitJavascript(this.operand1, TokenID.Dot, false);\n emitter.writeToOutput(\".\");\n emitter.emitJavascriptName(this.operand2, false);\n }\n break;\n case NodeType.Index:\n emitter.emitIndex(this.operand1, this.operand2);\n break;\n\n case NodeType.Member:\n if (this.operand2.nodeType == NodeType.FuncDecl && (this.operand2).isAccessor()) {\n var funcDecl = this.operand2;\n if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n emitter.writeToOutput(\"get \");\n }\n else {\n emitter.writeToOutput(\"set \");\n }\n emitter.emitJavascript(this.operand1, TokenID.Colon, false);\n }\n else {\n emitter.emitJavascript(this.operand1, TokenID.Colon, false);\n emitter.writeToOutputTrimmable(\": \");\n }\n emitter.emitJavascript(this.operand2, TokenID.Comma, false);\n break;\n case NodeType.Comma:\n emitter.emitJavascript(this.operand1, TokenID.Comma, false);\n if (emitter.emitState.inObjectLiteral) {\n emitter.writeLineToOutput(\", \");\n }\n else {\n emitter.writeToOutput(\",\");\n }\n emitter.emitJavascript(this.operand2, TokenID.Comma, false);\n break;\n case NodeType.Is:\n throw new Error(\"should be de-sugared during type check\");\n default:\n throw new Error(\"please implement in derived class\");\n }\n }\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class ConditionalExpression extends Expression {\n constructor (public operand1: AST,\n public operand2: AST,\n public operand3: AST) {\n super(NodeType.ConditionalExpression);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckQMark(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascript(this.operand1, TokenID.Question, false);\n emitter.writeToOutput(\" ? \");\n emitter.emitJavascript(this.operand2, TokenID.Question, false);\n emitter.writeToOutput(\" : \");\n emitter.emitJavascript(this.operand3, TokenID.Question, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class NumberLiteral extends Expression {\n constructor (public value: number, public hasEmptyFraction?: bool) {\n super(NodeType.NumberLit);\n }\n\n public isNegativeZero = false;\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.doubleType;\n return this;\n }\n\n public treeViewLabel() {\n return \"num: \" + this.printLabel();\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.isNegativeZero) {\n emitter.writeToOutput(\"-\");\n }\n\n emitter.writeToOutput(this.value.toString());\n\n if (this.hasEmptyFraction)\n emitter.writeToOutput(\".0\");\n\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public printLabel() {\n if (Math.floor(this.value) != this.value) {\n return this.value.toFixed(2).toString();\n }\n else if (this.hasEmptyFraction) {\n return this.value.toString() + \".0\";\n }\n else {\n return this.value.toString();\n }\n }\n }\n\n export class RegexLiteral extends Expression {\n constructor (public regex) {\n super(NodeType.Regex);\n }\n \n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.regexType;\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(this.regex.toString());\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class StringLiteral extends Expression {\n constructor (public text: string) {\n super(NodeType.QString);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.emitStringLiteral(this.text);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.stringType;\n return this;\n }\n\n public treeViewLabel() {\n return \"st: \" + this.text;\n }\n\n public printLabel() {\n return this.text;\n }\n }\n\n export class ModuleElement extends AST {\n constructor (nodeType: NodeType) {\n super(nodeType);\n }\n }\n\n export class ImportDeclaration extends ModuleElement {\n public isStatementOrExpression() { return true; }\n public varFlags = VarFlags.None;\n public isDynamicImport = false;\n public isDeclaration() { return true; }\n\n constructor (public id: Identifier, public alias: AST) {\n super(NodeType.ImportDeclaration);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n var mod = this.alias.type;\n // REVIEW: Only modules may be aliased for now, though there's no real\n // restriction on what the type symbol may be\n if (!this.isDynamicImport || (this.id.sym && !(this.id.sym).onlyReferencedAsTypeRef)) {\n var prevModAliasId = emitter.modAliasId;\n var prevFirstModAlias = emitter.firstModAlias;\n\n emitter.recordSourceMappingStart(this);\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.writeToOutput(\"var \" + this.id.actualText + \" = \");\n emitter.modAliasId = this.id.actualText;\n emitter.firstModAlias = this.firstAliasedModToString();\n emitter.emitJavascript(this.alias, TokenID.Tilde, false);\n // the dynamic import case will insert the semi-colon automatically\n if (!this.isDynamicImport) {\n emitter.writeToOutput(\";\");\n }\n emitter.emitParensAndCommentsInPlace(this, false);\n emitter.recordSourceMappingEnd(this);\n\n emitter.modAliasId = prevModAliasId;\n emitter.firstModAlias = prevFirstModAlias;\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckImportDecl(this);\n }\n\n public getAliasName(aliasAST?: AST = this.alias) : string {\n if (aliasAST.nodeType == NodeType.Name) {\n return (aliasAST).actualText;\n } else {\n var dotExpr = aliasAST;\n return this.getAliasName(dotExpr.operand1) + \".\" + this.getAliasName(dotExpr.operand2);\n }\n }\n\n public firstAliasedModToString() {\n if (this.alias.nodeType == NodeType.Name) {\n return (this.alias).actualText;\n }\n else {\n var dotExpr = this.alias;\n var firstMod = dotExpr.operand1;\n return firstMod.actualText;\n }\n }\n }\n\n export class BoundDecl extends AST {\n public init: AST = null;\n public typeExpr: AST = null;\n public varFlags = VarFlags.None;\n public sym: Symbol = null;\n public isDeclaration() { return true; }\n\n constructor (public id: Identifier, nodeType: NodeType, public nestingLevel: number) {\n super(nodeType);\n }\n\n public isStatementOrExpression() { return true; }\n\n public isPrivate() { return hasFlag(this.varFlags, VarFlags.Private); }\n public isPublic() { return hasFlag(this.varFlags, VarFlags.Public); }\n public isProperty() { return hasFlag(this.varFlags, VarFlags.Property); }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckBoundDecl(this);\n }\n\n public printLabel() {\n return this.treeViewLabel();\n }\n }\n\n export class VarDecl extends BoundDecl {\n constructor (id: Identifier, nest: number) {\n super(id, NodeType.VarDecl, nest);\n }\n\n public isAmbient() { return hasFlag(this.varFlags, VarFlags.Ambient); }\n public isExported() { return hasFlag(this.varFlags, VarFlags.Exported); }\n public isStatic() { return hasFlag(this.varFlags, VarFlags.Static); }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptVarDecl(this, tokenId);\n }\n\n public treeViewLabel() {\n return \"var \" + this.id.actualText;\n }\n }\n\n export class ArgDecl extends BoundDecl {\n constructor (id: Identifier) {\n super(id, NodeType.ArgDecl, 0);\n }\n\n public isOptional = false;\n\n public isOptionalArg() { return this.isOptional || this.init; }\n\n public treeViewLabel() {\n return \"arg: \" + this.id.actualText;\n }\n\n public parameterPropertySym: FieldSymbol = null;\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(this.id.actualText);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n var internalId = 0;\n\n export class FuncDecl extends AST {\n public hint: string = null;\n public fncFlags = FncFlags.None;\n public returnTypeAnnotation: AST = null;\n public symbols: IHashTable;\n public variableArgList = false;\n public signature: Signature;\n public envids: Identifier[];\n public jumpRefs: Identifier[] = null;\n public internalNameCache: string = null;\n public tmp1Declared = false;\n public enclosingFnc: FuncDecl = null;\n public freeVariables: Symbol[] = [];\n public unitIndex = -1;\n public classDecl: NamedDeclaration = null;\n public boundToProperty: VarDecl = null;\n public isOverload = false;\n public innerStaticFuncs: FuncDecl[] = [];\n public isTargetTypedAsMethod = false;\n public isInlineCallLiteral = false;\n public accessorSymbol: Symbol = null;\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public returnStatementsWithExpressions: ReturnStatement[] = [];\n public scopeType: Type = null; // Type of the FuncDecl, before target typing\n public endingToken: ASTSpan = null;\n public isDeclaration() { return true; }\n\n constructor (public name: Identifier, public bod: ASTList, public isConstructor: bool,\n public arguments: ASTList, public vars: ASTList, public scopes: ASTList, public statics: ASTList,\n nodeType: number) {\n\n super(nodeType);\n }\n\n public internalName(): string {\n if (this.internalNameCache == null) {\n var extName = this.getNameText();\n if (extName) {\n this.internalNameCache = \"_internal_\" + extName;\n }\n else {\n this.internalNameCache = \"_internal_\" + internalId++;\n }\n }\n return this.internalNameCache;\n }\n\n public hasSelfReference() { return hasFlag(this.fncFlags, FncFlags.HasSelfReference); }\n public setHasSelfReference() { this.fncFlags |= FncFlags.HasSelfReference; }\n\n public hasSuperReferenceInFatArrowFunction() { return hasFlag(this.fncFlags, FncFlags.HasSuperReferenceInFatArrowFunction); }\n public setHasSuperReferenceInFatArrowFunction() { this.fncFlags |= FncFlags.HasSuperReferenceInFatArrowFunction; }\n\n public addCloRef(id: Identifier, sym: Symbol): number {\n if (this.envids == null) {\n this.envids = new Identifier[];\n }\n this.envids[this.envids.length] = id;\n var outerFnc = this.enclosingFnc;\n if (sym) {\n while (outerFnc && (outerFnc.type.symbol != sym.container)) {\n outerFnc.addJumpRef(sym);\n outerFnc = outerFnc.enclosingFnc;\n }\n }\n return this.envids.length - 1;\n }\n\n public addJumpRef(sym: Symbol): void {\n if (this.jumpRefs == null) {\n this.jumpRefs = new Identifier[];\n }\n var id = new Identifier(sym.name);\n this.jumpRefs[this.jumpRefs.length] = id;\n id.sym = sym;\n id.cloId = this.addCloRef(id, null);\n }\n\n public buildControlFlow(): ControlFlowContext {\n var entry = new BasicBlock();\n var exit = new BasicBlock();\n\n var context = new ControlFlowContext(entry, exit);\n\n var controlFlowPrefix = (ast: AST, parent: AST, walker: IAstWalker) => {\n ast.addToControlFlow(walker.state);\n return ast;\n }\n\n var walker = getAstWalkerFactory().getWalker(controlFlowPrefix, null, null, context);\n context.walker = walker;\n walker.walk(this.bod, this);\n\n return context;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckFunction(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptFunction(this);\n }\n\n public getNameText() {\n if (this.name) {\n return this.name.actualText;\n }\n else {\n return this.hint;\n }\n }\n\n public isMethod() {\n return (this.fncFlags & FncFlags.Method) != FncFlags.None;\n }\n\n public isCallMember() { return hasFlag(this.fncFlags, FncFlags.CallMember); }\n public isConstructMember() { return hasFlag(this.fncFlags, FncFlags.ConstructMember); }\n public isIndexerMember() { return hasFlag(this.fncFlags, FncFlags.IndexerMember); }\n public isSpecialFn() { return this.isCallMember() || this.isIndexerMember() || this.isConstructMember(); }\n public isAnonymousFn() { return this.name === null; }\n public isAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor) || hasFlag(this.fncFlags, FncFlags.SetAccessor); }\n public isGetAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor); }\n public isSetAccessor() { return hasFlag(this.fncFlags, FncFlags.SetAccessor); }\n public isAmbient() { return hasFlag(this.fncFlags, FncFlags.Ambient); }\n public isExported() { return hasFlag(this.fncFlags, FncFlags.Exported); }\n public isPrivate() { return hasFlag(this.fncFlags, FncFlags.Private); }\n public isPublic() { return hasFlag(this.fncFlags, FncFlags.Public); }\n public isStatic() { return hasFlag(this.fncFlags, FncFlags.Static); }\n\n public treeViewLabel() {\n if (this.name == null) {\n return \"funcExpr\";\n }\n else {\n return \"func: \" + this.name.actualText\n }\n }\n\n public ClearFlags(): void {\n this.fncFlags = FncFlags.None;\n }\n\n public isSignature() { return (this.fncFlags & FncFlags.Signature) != FncFlags.None; }\n }\n\n export class LocationInfo {\n constructor (public filename: string, public lineMap: number[], public unitIndex) { }\n }\n\n export var unknownLocationInfo = new LocationInfo(\"unknown\", null, -1);\n\n export class Script extends FuncDecl {\n public locationInfo: LocationInfo = null;\n public referencedFiles: IFileReference[] = [];\n public requiresGlobal = false;\n public requiresExtendsBlock = false;\n public isResident = false;\n public isDeclareFile = false;\n public hasBeenTypeChecked = false;\n public topLevelMod: ModuleDeclaration = null;\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public vars: ASTList;\n public scopes: ASTList;\n // Remember if the script contains Unicode chars, that is needed when generating code for this script object to decide the output file correct encoding.\n public containsUnicodeChar = false;\n public containsUnicodeCharInComment = false;\n public cachedEmitRequired: bool;\n\n private setCachedEmitRequired(value: bool) {\n this.cachedEmitRequired = value;\n return this.cachedEmitRequired;\n }\n\n constructor (vars: ASTList, scopes: ASTList) {\n super(new Identifier(\"script\"), null, false, null, vars, scopes, null, NodeType.Script);\n this.vars = vars;\n this.scopes = scopes;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckScript(this);\n }\n\n public treeViewLabel() {\n return \"Script\";\n }\n\n public emitRequired(emitOptions: EmitOptions) {\n if (this.cachedEmitRequired != undefined) {\n return this.cachedEmitRequired;\n }\n\n if (!this.isDeclareFile && !this.isResident && this.bod) {\n if (this.bod.members.length == 0) {\n // allow empty files that are not declare files \n return this.setCachedEmitRequired(true);\n }\n\n for (var i = 0, len = this.bod.members.length; i < len; i++) {\n var stmt = this.bod.members[i];\n if (stmt.nodeType == NodeType.ModuleDeclaration) {\n if (!hasFlag((stmt).modFlags, ModuleFlags.ShouldEmitModuleDecl | ModuleFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.ClassDeclaration) {\n if (!hasFlag((stmt).varFlags, VarFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.VarDecl) {\n if (!hasFlag((stmt).varFlags, VarFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.FuncDecl) {\n if (!(stmt).isSignature()) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType != NodeType.InterfaceDeclaration && stmt.nodeType != NodeType.Empty) {\n return this.setCachedEmitRequired(true);\n }\n }\n\n if ( emitOptions.emitComments &&\n ((this.bod.preComments && this.bod.preComments.length > 0) || (this.bod.postComments && this.bod.postComments.length > 0))) {\n return this.setCachedEmitRequired(true);\n }\n }\n return this.setCachedEmitRequired(false);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n if (this.emitRequired(emitter.emitOptions)) {\n emitter.emitParensAndCommentsInPlace(this.bod, true);\n emitter.emitJavascriptList(this.bod, null, TokenID.Semicolon, true, false, false, true, this.requiresExtendsBlock);\n emitter.emitParensAndCommentsInPlace(this.bod, false);\n }\n }\n\n private externallyVisibleImportedSymbols: Symbol[] = [];\n\n public AddExternallyVisibleImportedSymbol(symbol: Symbol, checker: TypeChecker) {\n if (this.isExternallyVisibleSymbol(symbol)) {\n return;\n }\n\n // Before adding check if the external symbol is also marked for visibility\n if (!symbol.getType().symbol.isExternallyVisible(checker)) {\n // Report error\n var quotes = \"\";\n var moduleName = symbol.getType().symbol.prettyName;\n if (!isQuoted(moduleName)) {\n quotes = \"'\";\n }\n checker.errorReporter.simpleError(symbol.declAST, \"Externally visible import statement uses non exported module \" + quotes + moduleName + quotes);\n }\n this.externallyVisibleImportedSymbols.push(symbol);\n }\n\n public isExternallyVisibleSymbol(symbol: Symbol) {\n for (var i = 0 ; i < this.externallyVisibleImportedSymbols.length; i++) {\n if (this.externallyVisibleImportedSymbols[i] == symbol) {\n return true;\n }\n }\n return false;\n }\n }\n\n export class NamedDeclaration extends ModuleElement {\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public isDeclaration() { return true; }\n\n constructor (nodeType: NodeType,\n public name: Identifier,\n public members: ASTList) {\n super(nodeType);\n }\n }\n\n export class ModuleDeclaration extends NamedDeclaration {\n public modFlags = ModuleFlags.ShouldEmitModuleDecl;\n public mod: ModuleType;\n public prettyName: string;\n public amdDependencies: string[] = [];\n public vars: ASTList;\n public scopes: ASTList;\n // Remember if the module contains Unicode chars, that is needed for dynamic module as we will generate a file for each.\n public containsUnicodeChar = false;\n public containsUnicodeCharInComment = false;\n\n constructor (name: Identifier, members: ASTList, vars: ASTList, scopes: ASTList, public endingToken: ASTSpan) {\n super(NodeType.ModuleDeclaration, name, members);\n\n this.vars = vars;\n this.scopes = scopes;\n this.prettyName = this.name.actualText;\n }\n\n public isExported() { return hasFlag(this.modFlags, ModuleFlags.Exported); }\n public isAmbient() { return hasFlag(this.modFlags, ModuleFlags.Ambient); }\n public isEnum() { return hasFlag(this.modFlags, ModuleFlags.IsEnum); }\n\n public recordNonInterface() {\n this.modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckModule(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n if (!hasFlag(this.modFlags, ModuleFlags.ShouldEmitModuleDecl)) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.emitJavascriptModule(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n }\n\n export class TypeDeclaration extends NamedDeclaration {\n public varFlags = VarFlags.None;\n\n constructor (nodeType: NodeType,\n name: Identifier,\n public extendsList: ASTList,\n public implementsList: ASTList,\n members: ASTList) {\n super(nodeType, name, members);\n }\n\n public isExported() { \n return hasFlag(this.varFlags, VarFlags.Exported);\n }\n\n public isAmbient() {\n return hasFlag(this.varFlags, VarFlags.Ambient);\n }\n }\n\n export class ClassDeclaration extends TypeDeclaration {\n public knownMemberNames: any = {};\n public constructorDecl: FuncDecl = null;\n public constructorNestingLevel = 0;\n public endingToken: ASTSpan = null;\n\n constructor (name: Identifier,\n members: ASTList,\n extendsList: ASTList,\n implementsList: ASTList) {\n super(NodeType.ClassDeclaration, name, extendsList, implementsList, members);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckClass(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptClass(this);\n }\n }\n\n export class InterfaceDeclaration extends TypeDeclaration {\n constructor (name: Identifier,\n members: ASTList,\n extendsList: ASTList,\n implementsList: ASTList) {\n super(NodeType.InterfaceDeclaration, name, extendsList, implementsList, members);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckInterface(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n }\n }\n\n export class Statement extends ModuleElement {\n constructor (nodeType: NodeType) {\n super(nodeType);\n this.flags |= ASTFlags.IsStatement;\n }\n\n public isLoop() { return false; }\n\n public isStatementOrExpression() { return true; }\n\n public isCompoundStatement() { return this.isLoop(); }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.voidType;\n return this;\n }\n }\n\n export class LabeledStatement extends Statement {\n constructor (public labels: ASTList, public stmt: AST) {\n super(NodeType.LabeledStatement);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.labels) {\n var labelsLen = this.labels.members.length;\n for (var i = 0; i < labelsLen; i++) {\n this.labels.members[i].emit(emitter, tokenId, startLine);\n }\n }\n this.stmt.emit(emitter, tokenId, true);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n typeFlow.typeCheck(this.labels);\n this.stmt = this.stmt.typeCheck(typeFlow);\n return this;\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n var beforeBB = context.current;\n var bb = new BasicBlock();\n context.current = bb;\n beforeBB.addSuccessor(bb);\n }\n }\n\n export class Block extends Statement {\n constructor (public statements: ASTList,\n public isStatementBlock: bool) {\n super(NodeType.Block);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.isStatementBlock) {\n emitter.writeLineToOutput(\" {\");\n emitter.indenter.increaseIndent();\n } else {\n emitter.setInVarBlock(this.statements.members.length);\n }\n var temp = emitter.setInObjectLiteral(false);\n if (this.statements) {\n emitter.emitJavascriptList(this.statements, null, TokenID.Semicolon, true, false, false);\n }\n if (this.isStatementBlock) {\n emitter.indenter.decreaseIndent();\n emitter.emitIndent();\n emitter.writeToOutput(\"}\");\n }\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var afterIfNeeded = new BasicBlock();\n context.pushStatement(this, context.current, afterIfNeeded);\n if (this.statements) {\n context.walk(this.statements, this);\n }\n context.walker.options.goChildren = false;\n context.popStatement();\n if (afterIfNeeded.predecessors.length > 0) {\n context.current.addSuccessor(afterIfNeeded);\n context.current = afterIfNeeded;\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n if (!typeFlow.checker.styleSettings.emptyBlocks) {\n if ((this.statements === null) || (this.statements.members.length == 0)) {\n typeFlow.checker.errorReporter.styleError(this, \"empty block\");\n }\n }\n\n typeFlow.typeCheck(this.statements);\n return this;\n }\n }\n\n export class Jump extends Statement {\n public target: string = null;\n public hasExplicitTarget() { return (this.target); }\n public resolvedTarget: Statement = null;\n\n constructor (nodeType: NodeType) {\n super(nodeType);\n }\n\n public setResolvedTarget(parser: Parser, stmt: Statement): bool {\n if (stmt.isLoop()) {\n this.resolvedTarget = stmt;\n return true;\n }\n if (this.nodeType === NodeType.Continue) {\n parser.reportParseError(\"continue statement applies only to loops\");\n return false;\n }\n else {\n if ((stmt.nodeType == NodeType.Switch) || this.hasExplicitTarget()) {\n this.resolvedTarget = stmt;\n return true;\n }\n else {\n parser.reportParseError(\"break statement with no label can apply only to a loop or switch statement\");\n return false;\n }\n }\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n super.addToControlFlow(context);\n context.unconditionalBranch(this.resolvedTarget, (this.nodeType == NodeType.Continue));\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.nodeType == NodeType.Break) {\n emitter.writeToOutput(\"break\");\n }\n else {\n emitter.writeToOutput(\"continue\");\n }\n if (this.hasExplicitTarget()) {\n emitter.writeToOutput(\" \" + this.target);\n }\n emitter.recordSourceMappingEnd(this);\n emitter.writeToOutput(\";\");\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class WhileStatement extends Statement {\n public body: AST = null;\n\n constructor (public cond: AST) {\n super(NodeType.While);\n }\n\n public isLoop() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.writeToOutput(\"while(\");\n emitter.emitJavascript(this.cond, TokenID.While, false);\n emitter.writeToOutput(\")\");\n emitter.emitJavascriptStatements(this.body, false);\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckWhile(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n context.addContent(this.cond);\n var condBlock = context.current;\n var targetInfo: ITargetInfo = null;\n if (this.body) {\n context.current = new BasicBlock();\n condBlock.addSuccessor(context.current);\n context.pushStatement(this, loopStart, afterLoop);\n context.walk(this.body, this);\n targetInfo = context.popStatement();\n }\n if (!(context.noContinuation)) {\n var loopEnd = context.current;\n loopEnd.addSuccessor(loopStart);\n }\n context.current = afterLoop;\n condBlock.addSuccessor(afterLoop);\n // TODO: check for while (true) and then only continue if afterLoop has predecessors\n context.noContinuation = false;\n context.walker.options.goChildren = false;\n }\n }\n\n export class DoWhileStatement extends Statement {\n public body: AST = null;\n public whileAST: AST = null;\n public cond: AST = null;\n public isLoop() { return true; }\n\n constructor () {\n super(NodeType.DoWhile);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.writeToOutput(\"do\");\n emitter.emitJavascriptStatements(this.body, true);\n emitter.recordSourceMappingStart(this.whileAST);\n emitter.writeToOutput(\"while\");\n emitter.recordSourceMappingEnd(this.whileAST);\n emitter.writeToOutput('(');\n emitter.emitJavascript(this.cond, TokenID.CloseParen, false);\n emitter.writeToOutput(\")\");\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.writeToOutput(\";\");\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckDoWhile(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n var targetInfo: ITargetInfo = null;\n if (this.body) {\n context.pushStatement(this, loopStart, afterLoop);\n context.walk(this.body, this);\n targetInfo = context.popStatement();\n }\n if (!(context.noContinuation)) {\n var loopEnd = context.current;\n loopEnd.addSuccessor(loopStart);\n context.addContent(this.cond);\n // TODO: check for while (true) \n context.current = afterLoop;\n loopEnd.addSuccessor(afterLoop);\n }\n else {\n context.addUnreachable(this.cond);\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class IfStatement extends Statement {\n public thenBod: AST;\n public elseBod: AST = null;\n public statement: ASTSpan = new ASTSpan();\n\n constructor (public cond: AST) {\n super(NodeType.If);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"if(\");\n emitter.emitJavascript(this.cond, TokenID.If, false);\n emitter.writeToOutput(\")\");\n emitter.recordSourceMappingEnd(this.statement);\n emitter.emitJavascriptStatements(this.thenBod, true);\n if (this.elseBod) {\n if (this.elseBod.nodeType === NodeType.If) {\n emitter.writeToOutput(\" else \");\n this.elseBod.emit(emitter, tokenId, /*startLine:*/ false);\n }\n else {\n emitter.writeToOutput(\" else\");\n emitter.emitJavascriptStatements(this.elseBod, true);\n }\n }\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckIf(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n this.cond.addToControlFlow(context);\n var afterIf = new BasicBlock();\n var beforeIf = context.current;\n context.pushStatement(this, beforeIf, afterIf);\n var hasContinuation = false;\n context.current = new BasicBlock();\n beforeIf.addSuccessor(context.current);\n context.walk(this.thenBod, this);\n if (!context.noContinuation) {\n hasContinuation = true;\n context.current.addSuccessor(afterIf);\n }\n if (this.elseBod) {\n // current block will be thenBod\n context.current = new BasicBlock();\n context.noContinuation = false;\n beforeIf.addSuccessor(context.current);\n context.walk(this.elseBod, this);\n if (!context.noContinuation) {\n hasContinuation = true;\n context.current.addSuccessor(afterIf);\n }\n else {\n // thenBod created continuation for if statement\n if (hasContinuation) {\n context.noContinuation = false;\n }\n }\n }\n else {\n beforeIf.addSuccessor(afterIf);\n context.noContinuation = false;\n hasContinuation = true;\n }\n var targetInfo = context.popStatement();\n if (afterIf.predecessors.length > 0) {\n context.noContinuation = false;\n hasContinuation = true;\n }\n if (hasContinuation) {\n context.current = afterIf;\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class ReturnStatement extends Statement {\n public returnExpression: AST = null;\n\n constructor () {\n super(NodeType.Return);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n if (this.returnExpression) {\n emitter.writeToOutput(\"return \");\n emitter.emitJavascript(this.returnExpression, TokenID.Semicolon, false);\n\n if (this.returnExpression.nodeType === NodeType.FuncDecl) {\n emitter.writeToOutput(\";\");\n }\n }\n else {\n emitter.writeToOutput(\"return;\");\n }\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n super.addToControlFlow(context);\n context.returnStmt();\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckReturn(this);\n }\n }\n\n export class EndCode extends AST {\n constructor () {\n super(NodeType.EndCode);\n }\n }\n\n export class ForInStatement extends Statement {\n constructor (public lval: AST, public obj: AST) {\n super(NodeType.ForIn);\n if (this.lval && (this.lval.nodeType == NodeType.VarDecl)) {\n (this.lval).varFlags |= VarFlags.AutoInit;\n }\n }\n public statement: ASTSpan = new ASTSpan();\n public body: AST;\n\n public isLoop() { return true; }\n\n public isFiltered() {\n if (this.body) {\n var singleItem: AST = null;\n if (this.body.nodeType == NodeType.List) {\n var stmts = this.body;\n if (stmts.members.length == 1) {\n singleItem = stmts.members[0];\n }\n }\n else {\n singleItem = this.body;\n }\n // match template for filtering 'own' properties from obj\n if (singleItem !== null) {\n if (singleItem.nodeType == NodeType.Block) {\n var block = singleItem;\n if ((block.statements !== null) && (block.statements.members.length == 1)) {\n singleItem = block.statements.members[0];\n }\n }\n if (singleItem.nodeType == NodeType.If) {\n var cond = (singleItem).cond;\n if (cond.nodeType == NodeType.Call) {\n var target = (cond).target;\n if (target.nodeType == NodeType.Dot) {\n var binex = target;\n if ((binex.operand1.nodeType == NodeType.Name) &&\n (this.obj.nodeType == NodeType.Name) &&\n ((binex.operand1).actualText == (this.obj).actualText)) {\n var prop = binex.operand2;\n if (prop.actualText == \"hasOwnProperty\") {\n var args = (cond).arguments;\n if ((args !== null) && (args.members.length == 1)) {\n var arg = args.members[0];\n if ((arg.nodeType == NodeType.Name) &&\n (this.lval.nodeType == NodeType.Name)) {\n if (((this.lval).actualText) == (arg).actualText) {\n return true;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n return false;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"for(\");\n emitter.emitJavascript(this.lval, TokenID.For, false);\n emitter.writeToOutput(\" in \");\n emitter.emitJavascript(this.obj, TokenID.For, false);\n emitter.writeToOutput(\")\");\n emitter.recordSourceMappingEnd(this.statement);\n emitter.emitJavascriptStatements(this.body, true);\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n if (typeFlow.checker.styleSettings.forin) {\n if (!this.isFiltered()) {\n typeFlow.checker.errorReporter.styleError(this, \"no hasOwnProperty filter\");\n }\n }\n return typeFlow.typeCheckForIn(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n if (this.lval) {\n context.addContent(this.lval);\n }\n if (this.obj) {\n context.addContent(this.obj);\n }\n\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n if (this.body) {\n context.pushStatement(this, loopStart, afterLoop);\n context.walk(this.body, this);\n context.popStatement();\n }\n if (!(context.noContinuation)) {\n var loopEnd = context.current;\n loopEnd.addSuccessor(loopStart);\n }\n context.current = afterLoop;\n context.noContinuation = false;\n loopHeader.addSuccessor(afterLoop);\n context.walker.options.goChildren = false;\n }\n }\n\n export class ForStatement extends Statement {\n public cond: AST;\n public body: AST;\n public incr: AST;\n\n constructor (public init: AST) {\n super(NodeType.For);\n }\n\n public isLoop() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.writeToOutput(\"for(\");\n if (this.init) {\n if (this.init.nodeType != NodeType.List) {\n emitter.emitJavascript(this.init, TokenID.For, false);\n }\n else {\n emitter.setInVarBlock((this.init).members.length); \n emitter.emitJavascriptList(this.init, null, TokenID.For, false, false, false);\n }\n }\n emitter.writeToOutput(\"; \");\n emitter.emitJavascript(this.cond, TokenID.For, false);\n emitter.writeToOutput(\"; \");\n emitter.emitJavascript(this.incr, TokenID.For, false);\n emitter.writeToOutput(\")\");\n emitter.emitJavascriptStatements(this.body, true);\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckFor(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n if (this.init) {\n context.addContent(this.init);\n }\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n var condBlock: BasicBlock = null;\n var continueTarget = loopStart;\n var incrBB: BasicBlock = null;\n if (this.incr) {\n incrBB = new BasicBlock();\n continueTarget = incrBB;\n }\n if (this.cond) {\n condBlock = context.current;\n context.addContent(this.cond);\n context.current = new BasicBlock();\n condBlock.addSuccessor(context.current);\n }\n var targetInfo: ITargetInfo = null;\n if (this.body) {\n context.pushStatement(this, continueTarget, afterLoop);\n context.walk(this.body, this);\n targetInfo = context.popStatement();\n }\n if (this.incr) {\n if (context.noContinuation) {\n if (incrBB.predecessors.length == 0) {\n context.addUnreachable(this.incr);\n }\n }\n else {\n context.current.addSuccessor(incrBB);\n context.current = incrBB;\n context.addContent(this.incr);\n }\n }\n var loopEnd = context.current;\n if (!(context.noContinuation)) {\n loopEnd.addSuccessor(loopStart);\n\n }\n if (condBlock) {\n condBlock.addSuccessor(afterLoop);\n context.noContinuation = false;\n }\n if (afterLoop.predecessors.length > 0) {\n context.noContinuation = false;\n context.current = afterLoop;\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class WithStatement extends Statement {\n public body: AST;\n\n public isCompoundStatement() { return true; }\n\n public withSym: WithSymbol = null;\n\n constructor (public expr: AST) {\n super(NodeType.With);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"with (\");\n if (this.expr) {\n emitter.emitJavascript(this.expr, TokenID.With, false);\n }\n\n emitter.writeToOutput(\")\");\n emitter.emitJavascriptStatements(this.body, true);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckWith(this);\n }\n }\n\n export class SwitchStatement extends Statement {\n public caseList: ASTList;\n public defaultCase: CaseStatement = null;\n public statement: ASTSpan = new ASTSpan();\n\n constructor (public val: AST) {\n super(NodeType.Switch);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"switch(\");\n emitter.emitJavascript(this.val, TokenID.Identifier, false);\n emitter.writeToOutput(\")\"); \n emitter.recordSourceMappingEnd(this.statement);\n emitter.writeLineToOutput(\" {\");\n emitter.indenter.increaseIndent();\n var casesLen = this.caseList.members.length;\n for (var i = 0; i < casesLen; i++) {\n var caseExpr = this.caseList.members[i];\n emitter.emitJavascript(caseExpr, TokenID.Case, true);\n }\n emitter.indenter.decreaseIndent();\n emitter.emitIndent();\n emitter.writeToOutput(\"}\");\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var len = this.caseList.members.length;\n this.val = typeFlow.typeCheck(this.val);\n for (var i = 0; i < len; i++) {\n this.caseList.members[i] = typeFlow.typeCheck(this.caseList.members[i]);\n }\n this.defaultCase = typeFlow.typeCheck(this.defaultCase);\n this.type = typeFlow.voidType;\n return this;\n }\n\n // if there are break statements that match this switch, then just link cond block with block after switch\n public addToControlFlow(context: ControlFlowContext) {\n var condBlock = context.current;\n context.addContent(this.val);\n var execBlock = new BasicBlock();\n var afterSwitch = new BasicBlock();\n\n condBlock.addSuccessor(execBlock);\n context.pushSwitch(execBlock);\n context.current = execBlock;\n context.pushStatement(this, execBlock, afterSwitch);\n context.walk(this.caseList, this);\n context.popSwitch();\n var targetInfo = context.popStatement();\n var hasCondContinuation = (this.defaultCase == null);\n if (this.defaultCase == null) {\n condBlock.addSuccessor(afterSwitch);\n }\n if (afterSwitch.predecessors.length > 0) {\n context.noContinuation = false;\n context.current = afterSwitch;\n }\n else {\n context.noContinuation = true;\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class CaseStatement extends Statement {\n public expr: AST = null;\n public body: ASTList;\n\n constructor () {\n super(NodeType.Case);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.expr) {\n emitter.writeToOutput(\"case \");\n emitter.emitJavascript(this.expr, TokenID.Identifier, false);\n }\n else {\n emitter.writeToOutput(\"default\");\n }\n emitter.writeToOutput(\":\");\n if (this.body.members.length == 1 && this.body.members[0].nodeType == NodeType.Block) {\n // The case statement was written with curly braces, so emit it with the appropriate formatting\n emitter.emitJavascriptStatements(this.body, false);\n }\n else {\n // No curly braces. Format in the expected way\n emitter.writeLineToOutput(\"\");\n emitter.indenter.increaseIndent();\n emitter.emitBareJavascriptStatements(this.body);\n emitter.indenter.decreaseIndent();\n }\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.expr = typeFlow.typeCheck(this.expr);\n typeFlow.typeCheck(this.body);\n this.type = typeFlow.voidType;\n return this;\n }\n\n // TODO: more reasoning about unreachable cases (such as duplicate literals as case expressions)\n // for now, assume all cases are reachable, regardless of whether some cases fall through\n public addToControlFlow(context: ControlFlowContext) {\n var execBlock = new BasicBlock();\n var sw = context.currentSwitch[context.currentSwitch.length - 1];\n // TODO: fall-through from previous (+ to end of switch)\n if (this.expr) {\n var exprBlock = new BasicBlock();\n context.current = exprBlock;\n sw.addSuccessor(exprBlock);\n context.addContent(this.expr);\n exprBlock.addSuccessor(execBlock);\n }\n else {\n sw.addSuccessor(execBlock);\n }\n context.current = execBlock;\n if (this.body) {\n context.walk(this.body, this);\n }\n context.noContinuation = false;\n context.walker.options.goChildren = false;\n }\n }\n\n export class TypeReference extends AST {\n constructor (public term: AST, public arrayCount: number) {\n super(NodeType.TypeRef);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n throw new Error(\"should not emit a type ref\");\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var prevInTCTR = typeFlow.inTypeRefTypeCheck;\n typeFlow.inTypeRefTypeCheck = true;\n var typeLink = getTypeLink(this, typeFlow.checker, true);\n typeFlow.checker.resolveTypeLink(typeFlow.scope, typeLink, false);\n\n if (this.term) {\n typeFlow.typeCheck(this.term);\n }\n\n typeFlow.checkForVoidConstructor(typeLink.type, this);\n\n this.type = typeLink.type;\n\n // in error recovery cases, there may not be a term\n if (this.term) {\n this.term.type = this.type;\n }\n\n typeFlow.inTypeRefTypeCheck = prevInTCTR;\n return this;\n }\n }\n\n export class TryFinally extends Statement {\n constructor (public tryNode: AST, public finallyNode: Finally) {\n super(NodeType.TryFinally);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascript(this.tryNode, TokenID.Try, false);\n emitter.emitJavascript(this.finallyNode, TokenID.Finally, false);\n emitter.recordSourceMappingEnd(this);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.tryNode = typeFlow.typeCheck(this.tryNode);\n this.finallyNode = typeFlow.typeCheck(this.finallyNode);\n this.type = typeFlow.voidType;\n return this;\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var afterFinally = new BasicBlock();\n context.walk(this.tryNode, this);\n var finBlock = new BasicBlock();\n if (context.current) {\n context.current.addSuccessor(finBlock);\n }\n context.current = finBlock;\n context.pushStatement(this, null, afterFinally);\n context.walk(this.finallyNode, this);\n if (!context.noContinuation && context.current) {\n context.current.addSuccessor(afterFinally);\n }\n if (afterFinally.predecessors.length > 0) {\n context.current = afterFinally;\n }\n else {\n context.noContinuation = true;\n }\n context.popStatement();\n context.walker.options.goChildren = false;\n }\n }\n\n export class TryCatch extends Statement {\n constructor (public tryNode: Try, public catchNode: Catch) {\n super(NodeType.TryCatch);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascript(this.tryNode, TokenID.Try, false);\n emitter.emitJavascript(this.catchNode, TokenID.Catch, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var beforeTry = context.current;\n var tryBlock = new BasicBlock();\n beforeTry.addSuccessor(tryBlock);\n context.current = tryBlock;\n var afterTryCatch = new BasicBlock();\n context.pushStatement(this, null, afterTryCatch);\n context.walk(this.tryNode, this);\n if (!context.noContinuation) {\n if (context.current) {\n context.current.addSuccessor(afterTryCatch);\n }\n }\n context.current = new BasicBlock();\n beforeTry.addSuccessor(context.current);\n context.walk(this.catchNode, this);\n context.popStatement();\n if (!context.noContinuation) {\n if (context.current) {\n context.current.addSuccessor(afterTryCatch);\n }\n }\n context.current = afterTryCatch;\n context.walker.options.goChildren = false;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.tryNode = typeFlow.typeCheck(this.tryNode);\n this.catchNode = typeFlow.typeCheck(this.catchNode);\n this.type = typeFlow.voidType;\n return this;\n }\n }\n\n export class Try extends Statement {\n constructor (public body: AST) {\n super(NodeType.Try);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"try \");\n emitter.emitJavascript(this.body, TokenID.Try, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.body = typeFlow.typeCheck(this.body);\n return this;\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n if (this.body) {\n context.walk(this.body, this);\n }\n context.walker.options.goChildren = false;\n context.noContinuation = false;\n }\n }\n\n export class Catch extends Statement {\n constructor (public param: VarDecl, public body: AST) {\n super(NodeType.Catch);\n if (this.param) {\n this.param.varFlags |= VarFlags.AutoInit;\n }\n }\n public statement: ASTSpan = new ASTSpan();\n public containedScope: SymbolScope = null;\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\" \");\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"catch (\");\n emitter.emitJavascript(this.param, TokenID.OpenParen, false);\n emitter.writeToOutput(\")\");\n emitter.recordSourceMappingEnd(this.statement);\n emitter.emitJavascript(this.body, TokenID.Catch, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n if (this.param) {\n context.addContent(this.param);\n var bodBlock = new BasicBlock();\n context.current.addSuccessor(bodBlock);\n context.current = bodBlock;\n }\n if (this.body) {\n context.walk(this.body, this);\n }\n context.noContinuation = false;\n context.walker.options.goChildren = false;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var prevScope = typeFlow.scope;\n typeFlow.scope = this.containedScope;\n this.param = typeFlow.typeCheck(this.param);\n var exceptVar = new ValueLocation();\n var varSym = new VariableSymbol((this.param).id.text,\n this.param.minChar,\n typeFlow.checker.locationInfo.unitIndex,\n exceptVar);\n exceptVar.symbol = varSym;\n exceptVar.typeLink = new TypeLink();\n // var type for now (add syntax for type annotation)\n exceptVar.typeLink.type = typeFlow.anyType;\n var thisFnc = typeFlow.thisFnc;\n if (thisFnc && thisFnc.type) {\n exceptVar.symbol.container = thisFnc.type.symbol;\n }\n else {\n exceptVar.symbol.container = null;\n }\n this.param.sym = exceptVar.symbol;\n typeFlow.scope.enter(exceptVar.symbol.container, this.param, exceptVar.symbol,\n typeFlow.checker.errorReporter, false, false, false);\n this.body = typeFlow.typeCheck(this.body);\n\n // if we're in provisional typecheck mode, clean up the symbol entry\n // REVIEW: This is obviously bad form, since we're counting on the internal\n // layout of the symbol table, but this is also the only place where we insert\n // symbols during typecheck\n if (typeFlow.checker.inProvisionalTypecheckMode()) {\n var table = typeFlow.scope.getTable();\n (table).secondaryTable.table[exceptVar.symbol.name] = undefined;\n }\n this.type = typeFlow.voidType;\n typeFlow.scope = prevScope;\n return this;\n }\n }\n\n export class Finally extends Statement {\n constructor (public body: AST) {\n super(NodeType.Finally);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"finally\");\n emitter.emitJavascript(this.body, TokenID.Finally, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n if (this.body) {\n context.walk(this.body, this);\n }\n context.walker.options.goChildren = false;\n context.noContinuation = false;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.body = typeFlow.typeCheck(this.body);\n return this;\n }\n }\n\n export class Comment extends AST {\n\n public text: string[] = null;\n public minLine: number;\n public limLine: number;\n private docCommentText: string = null;\n\n constructor (public content: string, public isBlockComment: bool, public endsLine) {\n super(NodeType.Comment);\n }\n\n public getText(): string[] {\n if (this.text == null) {\n if (this.isBlockComment) {\n this.text = this.content.split(\"\\n\");\n for (var i = 0; i < this.text.length; i++) {\n this.text[i] = this.text[i].replace(/^\\s+|\\s+$/g, '');\n }\n }\n else {\n this.text = [(this.content.replace(/^\\s+|\\s+$/g, ''))];\n }\n }\n\n return this.text;\n }\n\n public isDocComment() {\n if (this.isBlockComment) {\n return this.content.charAt(2) == \"*\";\n }\n\n return false;\n }\n\n public getDocCommentText() {\n if (this.docCommentText == null) {\n this.docCommentText = Comment.cleanJSDocComment(this.content);\n }\n\n return this.docCommentText;\n }\n\n static consumeLeadingSpace(line: string, startIndex: number, maxSpacesToRemove?: number) {\n var endIndex = line.length;\n if (maxSpacesToRemove != undefined) {\n endIndex = min(startIndex + maxSpacesToRemove, endIndex);\n }\n\n for (; startIndex < endIndex; startIndex++) {\n var charCode = line.charCodeAt(startIndex);\n if (charCode != LexCodeSpace && charCode != LexCodeTAB) {\n return startIndex;\n }\n }\n \n if (endIndex != line.length) {\n return endIndex;\n }\n\n return -1;\n }\n\n static isSpaceChar(line: string, index: number) {\n var length = line.length;\n if (index < length) {\n var charCode = line.charCodeAt(index);\n // If the character is space\n return charCode == LexCodeSpace || charCode == LexCodeTAB;\n }\n\n // If the index is end of the line it is space\n return index == length;\n }\n\n static cleanDocCommentLine(line: string, jsDocStyleComment: bool, jsDocLineSpaceToRemove?: number) {\n var nonSpaceIndex = Comment.consumeLeadingSpace(line, 0);\n if (nonSpaceIndex != -1) {\n var jsDocSpacesRemoved = nonSpaceIndex;\n if (jsDocStyleComment && line.charAt(nonSpaceIndex) == '*') { // remove leading * in case of jsDocComment\n var startIndex = nonSpaceIndex + 1;\n nonSpaceIndex = Comment.consumeLeadingSpace(line, startIndex, jsDocLineSpaceToRemove);\n\n if (nonSpaceIndex != -1) {\n jsDocSpacesRemoved = nonSpaceIndex - startIndex;\n } else {\n return null;\n }\n }\n\n return {\n minChar: nonSpaceIndex,\n limChar: line.charAt(line.length - 1) == \"\\r\" ? line.length - 1 : line.length,\n jsDocSpacesRemoved: jsDocSpacesRemoved\n };\n }\n\n return null;\n }\n\n static cleanJSDocComment(content: string, spacesToRemove?: number) {\n var docCommentLines: string[] = [];\n content = content.replace(\"/**\", \"\"); // remove /**\n if (content.length >= 2 && content.charAt(content.length - 1) == \"/\" && content.charAt(content.length - 2) == \"*\") {\n content = content.substring(0, content.length - 2); // remove last */\n }\n var lines = content.split(\"\\n\");\n var inParamTag = false;\n for (var l = 0; l < lines.length; l++) {\n var line = lines[l];\n var cleanLinePos = Comment.cleanDocCommentLine(line, true, spacesToRemove);\n if (!cleanLinePos) {\n // Whole line empty, read next line\n continue;\n }\n\n var docCommentText = \"\";\n var prevPos = cleanLinePos.minChar;\n for (var i = line.indexOf(\"@\", cleanLinePos.minChar); 0 <= i && i < cleanLinePos.limChar; i = line.indexOf(\"@\", i + 1)) {\n // We have encoutered @. \n // If we were omitting param comment, we dont have to do anything\n // other wise the content of the text till @ tag goes as doc comment\n var wasInParamtag = inParamTag;\n\n // Parse contents next to @\n if (line.indexOf(\"param\", i + 1) == i + 1 && Comment.isSpaceChar(line, i + 6)) {\n // It is param tag. \n\n // If we were not in param tag earlier, push the contents from prev pos of the tag this tag start as docComment\n if (!wasInParamtag) {\n docCommentText += line.substring(prevPos, i);\n }\n\n // New start of contents \n prevPos = i;\n inParamTag = true;\n } else if (wasInParamtag) {\n // Non param tag start\n prevPos = i;\n inParamTag = false;\n }\n }\n\n if (!inParamTag) {\n docCommentText += line.substring(prevPos, cleanLinePos.limChar);\n }\n\n // Add line to comment text if it is not only white space line\n var newCleanPos = Comment.cleanDocCommentLine(docCommentText, false);\n if (newCleanPos) {\n if (spacesToRemove == undefined) {\n spacesToRemove = cleanLinePos.jsDocSpacesRemoved;\n }\n docCommentLines.push(docCommentText);\n }\n }\n \n return docCommentLines.join(\"\\n\");\n }\n\n static getDocCommentText(comments: Comment[]) {\n var docCommentText: string[] = [];\n for (var c = 0 ; c < comments.length; c++) {\n var commentText = comments[c].getDocCommentText();\n if (commentText != \"\") {\n docCommentText.push(commentText);\n }\n }\n return docCommentText.join(\"\\n\");\n }\n\n static getParameterDocCommentText(param: string, fncDocComments: Comment[]) {\n if (fncDocComments.length == 0 || !fncDocComments[0].isBlockComment) {\n // there were no fnc doc comments and the comment is not block comment then it cannot have \n // @param comment that can be parsed\n return \"\";\n }\n \n for (var i = 0; i < fncDocComments.length; i++) {\n var commentContents = fncDocComments[i].content;\n for (var j = commentContents.indexOf(\"@param\", 0); 0 <= j; j = commentContents.indexOf(\"@param\", j)) {\n j += 6;\n if (!Comment.isSpaceChar(commentContents, j)) {\n // This is not param tag but a tag line @paramxxxxx\n continue;\n }\n\n // This is param tag. Check if it is what we are looking for\n j = Comment.consumeLeadingSpace(commentContents, j);\n if (j == -1) {\n break;\n }\n \n // Ignore the type expression\n if (commentContents.charCodeAt(j) == LexCodeLC) {\n j++;\n // Consume the type\n var charCode = 0;\n for (var curlies = 1; j < commentContents.length; j++) {\n charCode = commentContents.charCodeAt(j);\n // { character means we need to find another } to match the found one\n if (charCode == LexCodeLC) {\n curlies++;\n continue;\n }\n\n // } char\n if (charCode == LexCodeRC) {\n curlies--;\n if (curlies == 0) {\n // We do not have any more } to match the type expression is ignored completely\n break;\n } else {\n // there are more { to be matched with }\n continue;\n }\n }\n\n // Found start of another tag\n if (charCode == LexCodeAtSign) {\n break;\n }\n }\n\n // End of the comment\n if (j == commentContents.length) {\n break;\n }\n\n // End of the tag, go onto looking for next tag\n if (charCode == LexCodeAtSign) {\n continue;\n }\n\n j = Comment.consumeLeadingSpace(commentContents, j + 1);\n if (j == -1) {\n break;\n }\n }\n\n // Parameter name\n if (param != commentContents.substr(j, param.length) || !Comment.isSpaceChar(commentContents, j + param.length)) {\n // this is not the parameter we are looking for\n continue;\n }\n\n // Found the parameter we were looking for\n j = Comment.consumeLeadingSpace(commentContents, j + param.length);\n if (j == -1) {\n return \"\";\n }\n \n var endOfParam = commentContents.indexOf(\"@\", j);\n var paramHelpString = commentContents.substring(j, endOfParam < 0 ? commentContents.length : endOfParam);\n\n // Find alignement spaces to remove\n var paramSpacesToRemove: number = undefined;\n var paramLineIndex = commentContents.substring(0, j).lastIndexOf(\"\\n\") + 1;\n if (paramLineIndex != 0) {\n if (paramLineIndex < j && commentContents.charAt(paramLineIndex + 1) == \"\\r\") {\n paramLineIndex++;\n }\n }\n var startSpaceRemovalIndex = Comment.consumeLeadingSpace(commentContents, paramLineIndex);\n if (startSpaceRemovalIndex != j && commentContents.charAt(startSpaceRemovalIndex) == \"*\") {\n paramSpacesToRemove = j - startSpaceRemovalIndex - 1;\n }\n\n // Clean jsDocComment and return\n return Comment.cleanJSDocComment(paramHelpString, paramSpacesToRemove);\n }\n }\n\n return \"\";\n }\n\n static getDocCommentTextOfSignatures(signatures: Signature[]) {\n var comments: string[] = [];\n for (var i = 0; i < signatures.length; i++) {\n var signatureDocComment = TypeScript.Comment.getDocCommentText(signatures[i].declAST.getDocComments());\n if (signatureDocComment != \"\") {\n comments.push(signatureDocComment);\n }\n }\n\n return comments.join(\"\\n\");\n }\n }\n\n export class DebuggerStatement extends Statement {\n constructor () {\n super(NodeType.Debugger);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeLineToOutput(\"debugger;\");\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///\n\nmodule TypeScript.AstWalkerWithDetailCallback {\n export interface AstWalkerDetailCallback {\n EmptyCallback? (pre, ast: AST): bool;\n EmptyExprCallback? (pre, ast: AST): bool;\n TrueCallback? (pre, ast: AST): bool;\n FalseCallback? (pre, ast: AST): bool;\n ThisCallback? (pre, ast: AST): bool;\n SuperCallback? (pre, ast: AST): bool;\n QStringCallback? (pre, ast: AST): bool;\n RegexCallback? (pre, ast: AST): bool;\n NullCallback? (pre, ast: AST): bool;\n ArrayLitCallback? (pre, ast: AST): bool;\n ObjectLitCallback? (pre, ast: AST): bool;\n VoidCallback? (pre, ast: AST): bool;\n CommaCallback? (pre, ast: AST): bool;\n PosCallback? (pre, ast: AST): bool;\n NegCallback? (pre, ast: AST): bool;\n DeleteCallback? (pre, ast: AST): bool;\n AwaitCallback? (pre, ast: AST): bool;\n InCallback? (pre, ast: AST): bool;\n DotCallback? (pre, ast: AST): bool;\n FromCallback? (pre, ast: AST): bool;\n IsCallback? (pre, ast: AST): bool;\n InstOfCallback? (pre, ast: AST): bool;\n TypeofCallback? (pre, ast: AST): bool;\n NumberLitCallback? (pre, ast: AST): bool;\n NameCallback? (pre, identifierAst: Identifier): bool;\n TypeRefCallback? (pre, ast: AST): bool;\n IndexCallback? (pre, ast: AST): bool;\n CallCallback? (pre, ast: AST): bool;\n NewCallback? (pre, ast: AST): bool;\n AsgCallback? (pre, ast: AST): bool;\n AsgAddCallback? (pre, ast: AST): bool;\n AsgSubCallback? (pre, ast: AST): bool;\n AsgDivCallback? (pre, ast: AST): bool;\n AsgMulCallback? (pre, ast: AST): bool;\n AsgModCallback? (pre, ast: AST): bool;\n AsgAndCallback? (pre, ast: AST): bool;\n AsgXorCallback? (pre, ast: AST): bool;\n AsgOrCallback? (pre, ast: AST): bool;\n AsgLshCallback? (pre, ast: AST): bool;\n AsgRshCallback? (pre, ast: AST): bool;\n AsgRs2Callback? (pre, ast: AST): bool;\n QMarkCallback? (pre, ast: AST): bool;\n LogOrCallback? (pre, ast: AST): bool;\n LogAndCallback? (pre, ast: AST): bool;\n OrCallback? (pre, ast: AST): bool;\n XorCallback? (pre, ast: AST): bool;\n AndCallback? (pre, ast: AST): bool;\n EqCallback? (pre, ast: AST): bool;\n NeCallback? (pre, ast: AST): bool;\n EqvCallback? (pre, ast: AST): bool;\n NEqvCallback? (pre, ast: AST): bool;\n LtCallback? (pre, ast: AST): bool;\n LeCallback? (pre, ast: AST): bool;\n GtCallback? (pre, ast: AST): bool;\n GeCallback? (pre, ast: AST): bool;\n AddCallback? (pre, ast: AST): bool;\n SubCallback? (pre, ast: AST): bool;\n MulCallback? (pre, ast: AST): bool;\n DivCallback? (pre, ast: AST): bool;\n ModCallback? (pre, ast: AST): bool;\n LshCallback? (pre, ast: AST): bool;\n RshCallback? (pre, ast: AST): bool;\n Rs2Callback? (pre, ast: AST): bool;\n NotCallback? (pre, ast: AST): bool;\n LogNotCallback? (pre, ast: AST): bool;\n IncPreCallback? (pre, ast: AST): bool;\n DecPreCallback? (pre, ast: AST): bool;\n IncPostCallback? (pre, ast: AST): bool;\n DecPostCallback? (pre, ast: AST): bool;\n TypeAssertionCallback? (pre, ast: AST): bool;\n FuncDeclCallback? (pre, funcDecl: FuncDecl): bool;\n MemberCallback? (pre, ast: AST): bool;\n VarDeclCallback? (pre, varDecl: VarDecl): bool;\n ArgDeclCallback? (pre, ast: AST): bool;\n ReturnCallback? (pre, ast: AST): bool;\n BreakCallback? (pre, ast: AST): bool;\n ContinueCallback? (pre, ast: AST): bool;\n ThrowCallback? (pre, ast: AST): bool;\n ForCallback? (pre, ast: AST): bool;\n ForInCallback? (pre, ast: AST): bool;\n IfCallback? (pre, ast: AST): bool;\n WhileCallback? (pre, ast: AST): bool;\n DoWhileCallback? (pre, ast: AST): bool;\n BlockCallback? (pre, block: Block): bool;\n CaseCallback? (pre, ast: AST): bool;\n SwitchCallback? (pre, ast: AST): bool;\n TryCallback? (pre, ast: AST): bool;\n TryCatchCallback? (pre, ast: AST): bool;\n TryFinallyCallback? (pre, ast: AST): bool;\n FinallyCallback? (pre, ast: AST): bool;\n CatchCallback? (pre, ast: AST): bool;\n ListCallback? (pre, astList: ASTList): bool;\n ScriptCallback? (pre, script: Script): bool;\n ClassDeclarationCallback? (pre, ast: AST): bool;\n InterfaceDeclarationCallback? (pre, interfaceDecl: InterfaceDeclaration): bool;\n ModuleDeclarationCallback? (pre, moduleDecl: ModuleDeclaration): bool;\n ImportDeclarationCallback? (pre, ast: AST): bool;\n WithCallback? (pre, ast: AST): bool;\n LabelCallback? (pre, labelAST: AST): bool;\n LabeledStatementCallback? (pre, ast: AST): bool;\n EBStartCallback? (pre, ast: AST): bool;\n GotoEBCallback? (pre, ast: AST): bool;\n EndCodeCallback? (pre, ast: AST): bool;\n ErrorCallback? (pre, ast: AST): bool;\n CommentCallback? (pre, ast: AST): bool;\n DebuggerCallback? (pre, ast: AST): bool;\n DefaultCallback? (pre, ast: AST): bool;\n }\n\n export function walk(script: Script, callback: AstWalkerDetailCallback): void {\n var pre = (cur: AST, parent: AST) => {\n walker.options.goChildren = AstWalkerCallback(true, cur, callback);\n return cur;\n }\n\n var post = (cur: AST, parent: AST) => {\n AstWalkerCallback(false, cur, callback);\n return cur;\n }\n\n var walker = TypeScript.getAstWalkerFactory().getWalker(pre, post);\n walker.walk(script, null);\n }\n\n function AstWalkerCallback(pre: bool, ast: AST, callback: AstWalkerDetailCallback): bool {\n // See if the Callback needs to be handled using specific one or default one\n var nodeType = ast.nodeType;\n var callbackString = (NodeType)._map[nodeType] + \"Callback\";\n if (callback[callbackString]) {\n return callback[callbackString](pre, ast);\n }\n\n if (callback.DefaultCallback) {\n return callback.DefaultCallback(pre, ast);\n }\n\n return true;\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///\n\nmodule TypeScript {\n export interface IAstWalker {\n walk(ast: AST, parent: AST): AST;\n options: AstWalkOptions;\n state: any; // user state object\n }\n\n export class AstWalkOptions {\n public goChildren = true;\n public goNextSibling = true;\n public reverseSiblings = false; // visit siblings in reverse execution order\n\n public stopWalk(stop:bool = true) {\n this.goChildren = !stop;\n this.goNextSibling = !stop;\n }\n }\n\n export interface IAstWalkCallback {\n (ast: AST, parent: AST, walker: IAstWalker): AST;\n }\n\n export interface IAstWalkChildren {\n (preAst: AST, parent: AST, walker: IAstWalker): void;\n }\n\n class AstWalker implements IAstWalker {\n constructor (\n private childrenWalkers: IAstWalkChildren[],\n private pre: IAstWalkCallback,\n private post: IAstWalkCallback,\n public options: AstWalkOptions,\n public state: any) {\n }\n\n public walk(ast: AST, parent: AST): AST {\n var preAst = this.pre(ast, parent, this);\n if (preAst === undefined) {\n preAst = ast;\n }\n if (this.options.goChildren) {\n var svGoSib = this.options.goNextSibling;\n this.options.goNextSibling = true;\n // Call the \"walkChildren\" function corresponding to \"nodeType\".\n this.childrenWalkers[ast.nodeType](ast, parent, this);\n this.options.goNextSibling = svGoSib;\n }\n else {\n // no go only applies to children of node issuing it\n this.options.goChildren = true;\n }\n if (this.post) {\n var postAst = this.post(preAst, parent, this);\n if (postAst === undefined) {\n postAst = preAst;\n }\n return postAst;\n }\n else {\n return preAst;\n }\n }\n }\n\n export class AstWalkerFactory {\n private childrenWalkers: IAstWalkChildren[] = [];\n\n constructor () {\n this.initChildrenWalkers();\n }\n\n public walk(ast: AST, pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): AST {\n return this.getWalker(pre, post, options, state).walk(ast, null)\n }\n\n public getWalker(pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): IAstWalker {\n return this.getSlowWalker(pre, post, options, state);\n }\n\n private getSlowWalker(pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): IAstWalker {\n if (!options) {\n options = new AstWalkOptions();\n }\n\n return new AstWalker(this.childrenWalkers, pre, post, options, state);\n }\n\n private initChildrenWalkers(): void {\n this.childrenWalkers[NodeType.None] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Empty] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.EmptyExpr] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.True] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.False] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.This] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Super] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.QString] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Regex] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Null] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.ArrayLit] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.ObjectLit] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Void] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Comma] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Pos] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Neg] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Delete] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Await] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.In] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Dot] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.From] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Is] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.InstOf] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Typeof] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.NumberLit] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Name] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.TypeRef] = ChildrenWalkers.walkTypeReferenceChildren;\n this.childrenWalkers[NodeType.Index] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Call] = ChildrenWalkers.walkCallExpressionChildren;\n this.childrenWalkers[NodeType.New] = ChildrenWalkers.walkCallExpressionChildren;\n this.childrenWalkers[NodeType.Asg] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgAdd] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgSub] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgDiv] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgMul] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgMod] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgAnd] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgXor] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgOr] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgLsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgRsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgRs2] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.ConditionalExpression] = ChildrenWalkers.walkTrinaryExpressionChildren;\n this.childrenWalkers[NodeType.LogOr] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.LogAnd] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Or] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Xor] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.And] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Eq] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Ne] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Eqv] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.NEqv] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Lt] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Le] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Gt] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Ge] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Add] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Sub] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Mul] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Div] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Mod] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Lsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Rsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Rs2] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Not] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.LogNot] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.IncPre] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.DecPre] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.IncPost] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.DecPost] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.TypeAssertion] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.FuncDecl] = ChildrenWalkers.walkFuncDeclChildren;\n this.childrenWalkers[NodeType.Member] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.VarDecl] = ChildrenWalkers.walkBoundDeclChildren;\n this.childrenWalkers[NodeType.ArgDecl] = ChildrenWalkers.walkBoundDeclChildren;\n this.childrenWalkers[NodeType.Return] = ChildrenWalkers.walkReturnStatementChildren;\n this.childrenWalkers[NodeType.Break] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Continue] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Throw] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.For] = ChildrenWalkers.walkForStatementChildren;\n this.childrenWalkers[NodeType.ForIn] = ChildrenWalkers.walkForInStatementChildren;\n this.childrenWalkers[NodeType.If] = ChildrenWalkers.walkIfStatementChildren;\n this.childrenWalkers[NodeType.While] = ChildrenWalkers.walkWhileStatementChildren;\n this.childrenWalkers[NodeType.DoWhile] = ChildrenWalkers.walkDoWhileStatementChildren;\n this.childrenWalkers[NodeType.Block] = ChildrenWalkers.walkBlockChildren;\n this.childrenWalkers[NodeType.Case] = ChildrenWalkers.walkCaseStatementChildren;\n this.childrenWalkers[NodeType.Switch] = ChildrenWalkers.walkSwitchStatementChildren;\n this.childrenWalkers[NodeType.Try] = ChildrenWalkers.walkTryChildren;\n this.childrenWalkers[NodeType.TryCatch] = ChildrenWalkers.walkTryCatchChildren;\n this.childrenWalkers[NodeType.TryFinally] = ChildrenWalkers.walkTryFinallyChildren;\n this.childrenWalkers[NodeType.Finally] = ChildrenWalkers.walkFinallyChildren;\n this.childrenWalkers[NodeType.Catch] = ChildrenWalkers.walkCatchChildren;\n this.childrenWalkers[NodeType.List] = ChildrenWalkers.walkListChildren;\n this.childrenWalkers[NodeType.Script] = ChildrenWalkers.walkScriptChildren;\n this.childrenWalkers[NodeType.ClassDeclaration] = ChildrenWalkers.walkClassDeclChildren;\n this.childrenWalkers[NodeType.InterfaceDeclaration] = ChildrenWalkers.walkTypeDeclChildren;\n this.childrenWalkers[NodeType.ModuleDeclaration] = ChildrenWalkers.walkModuleDeclChildren;\n this.childrenWalkers[NodeType.ImportDeclaration] = ChildrenWalkers.walkImportDeclChildren;\n this.childrenWalkers[NodeType.With] = ChildrenWalkers.walkWithStatementChildren;\n this.childrenWalkers[NodeType.Label] = ChildrenWalkers.walkLabelChildren;\n this.childrenWalkers[NodeType.LabeledStatement] = ChildrenWalkers.walkLabeledStatementChildren;\n this.childrenWalkers[NodeType.EBStart] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.GotoEB] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.EndCode] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Error] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Comment] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Debugger] = ChildrenWalkers.walkNone;\n\n // Verify the code is up to date with the enum\n for (var e in (NodeType)._map) {\n if ((this.childrenWalkers)[e] === undefined) {\n throw new Error(\"initWalkers function is not up to date with enum content!\");\n }\n }\n }\n }\n\n var globalAstWalkerFactory: AstWalkerFactory;\n\n export function getAstWalkerFactory(): AstWalkerFactory {\n if (!globalAstWalkerFactory) {\n globalAstWalkerFactory = new AstWalkerFactory();\n }\n return globalAstWalkerFactory;\n }\n\n module ChildrenWalkers {\n export function walkNone(preAst: ASTList, parent: AST, walker: IAstWalker): void {\n // Nothing to do\n }\n\n export function walkListChildren(preAst: ASTList, parent: AST, walker: IAstWalker): void {\n var len = preAst.members.length;\n if (walker.options.reverseSiblings) {\n for (var i = len - 1; i >= 0; i--) {\n if (walker.options.goNextSibling) {\n preAst.members[i] = walker.walk(preAst.members[i], preAst);\n }\n }\n }\n else {\n for (var i = 0; i < len; i++) {\n if (walker.options.goNextSibling) {\n preAst.members[i] = walker.walk(preAst.members[i], preAst);\n }\n }\n }\n }\n\n export function walkUnaryExpressionChildren(preAst: UnaryExpression, parent: AST, walker: IAstWalker): void {\n if (preAst.castTerm) {\n preAst.castTerm = walker.walk(preAst.castTerm, preAst);\n }\n if (preAst.operand) {\n preAst.operand = walker.walk(preAst.operand, preAst);\n }\n }\n\n export function walkBinaryExpressionChildren(preAst: BinaryExpression, parent: AST, walker: IAstWalker): void {\n if (walker.options.reverseSiblings) {\n if (preAst.operand2) {\n preAst.operand2 = walker.walk(preAst.operand2, preAst);\n }\n if ((preAst.operand1) && (walker.options.goNextSibling)) {\n preAst.operand1 = walker.walk(preAst.operand1, preAst);\n }\n } else {\n if (preAst.operand1) {\n preAst.operand1 = walker.walk(preAst.operand1, preAst);\n }\n if ((preAst.operand2) && (walker.options.goNextSibling)) {\n preAst.operand2 = walker.walk(preAst.operand2, preAst);\n }\n }\n }\n\n export function walkTypeReferenceChildren(preAst: TypeReference, parent: AST, walker: IAstWalker): void {\n if (preAst.term) {\n preAst.term = walker.walk(preAst.term, preAst);\n }\n }\n\n export function walkCallExpressionChildren(preAst: CallExpression, parent: AST, walker: IAstWalker): void {\n if (!walker.options.reverseSiblings) {\n preAst.target = walker.walk(preAst.target, preAst);\n }\n if (preAst.arguments && (walker.options.goNextSibling)) {\n preAst.arguments = walker.walk(preAst.arguments, preAst);\n }\n if ((walker.options.reverseSiblings) && (walker.options.goNextSibling)) {\n preAst.target = walker.walk(preAst.target, preAst);\n }\n }\n\n export function walkTrinaryExpressionChildren(preAst: ConditionalExpression, parent: AST, walker: IAstWalker): void {\n if (preAst.operand1) {\n preAst.operand1 = walker.walk(preAst.operand1, preAst);\n }\n if (preAst.operand2 && (walker.options.goNextSibling)) {\n preAst.operand2 = walker.walk(preAst.operand2, preAst);\n }\n if (preAst.operand3 && (walker.options.goNextSibling)) {\n preAst.operand3 = walker.walk(preAst.operand3, preAst);\n }\n }\n\n export function walkFuncDeclChildren(preAst: FuncDecl, parent: AST, walker: IAstWalker): void {\n if (preAst.name) {\n preAst.name = walker.walk(preAst.name, preAst);\n }\n if (preAst.arguments && (preAst.arguments.members.length > 0) && (walker.options.goNextSibling)) {\n preAst.arguments = walker.walk(preAst.arguments, preAst);\n }\n if (preAst.returnTypeAnnotation && (walker.options.goNextSibling)) {\n preAst.returnTypeAnnotation = walker.walk(preAst.returnTypeAnnotation, preAst);\n }\n if (preAst.bod && (preAst.bod.members.length > 0) && (walker.options.goNextSibling)) {\n preAst.bod = walker.walk(preAst.bod, preAst);\n }\n }\n\n export function walkBoundDeclChildren(preAst: BoundDecl, parent: AST, walker: IAstWalker): void {\n if (preAst.id) {\n preAst.id = walker.walk(preAst.id, preAst);\n }\n if (preAst.init) {\n preAst.init = walker.walk(preAst.init, preAst);\n }\n if ((preAst.typeExpr) && (walker.options.goNextSibling)) {\n preAst.typeExpr = walker.walk(preAst.typeExpr, preAst);\n }\n }\n\n export function walkReturnStatementChildren(preAst: ReturnStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.returnExpression) {\n preAst.returnExpression = walker.walk(preAst.returnExpression, preAst);\n }\n }\n\n export function walkForStatementChildren(preAst: ForStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.init) {\n preAst.init = walker.walk(preAst.init, preAst);\n }\n\n if (preAst.cond && walker.options.goNextSibling) {\n preAst.cond = walker.walk(preAst.cond, preAst);\n }\n\n if (preAst.incr && walker.options.goNextSibling) {\n preAst.incr = walker.walk(preAst.incr, preAst);\n }\n\n if (preAst.body && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkForInStatementChildren(preAst: ForInStatement, parent: AST, walker: IAstWalker): void {\n preAst.lval = walker.walk(preAst.lval, preAst);\n if (walker.options.goNextSibling) {\n preAst.obj = walker.walk(preAst.obj, preAst);\n }\n if (preAst.body && (walker.options.goNextSibling)) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkIfStatementChildren(preAst: IfStatement, parent: AST, walker: IAstWalker): void {\n preAst.cond = walker.walk(preAst.cond, preAst);\n if (preAst.thenBod && (walker.options.goNextSibling)) {\n preAst.thenBod = walker.walk(preAst.thenBod, preAst);\n }\n if (preAst.elseBod && (walker.options.goNextSibling)) {\n preAst.elseBod = walker.walk(preAst.elseBod, preAst);\n }\n }\n\n export function walkWhileStatementChildren(preAst: WhileStatement, parent: AST, walker: IAstWalker): void {\n preAst.cond = walker.walk(preAst.cond, preAst);\n if (preAst.body && (walker.options.goNextSibling)) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkDoWhileStatementChildren(preAst: DoWhileStatement, parent: AST, walker: IAstWalker): void {\n preAst.cond = walker.walk(preAst.cond, preAst);\n if (preAst.body && (walker.options.goNextSibling)) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkBlockChildren(preAst: Block, parent: AST, walker: IAstWalker): void {\n if (preAst.statements) {\n preAst.statements = walker.walk(preAst.statements, preAst);\n }\n }\n\n export function walkCaseStatementChildren(preAst: CaseStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.expr) {\n preAst.expr = walker.walk(preAst.expr, preAst);\n }\n\n if (preAst.body && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkSwitchStatementChildren(preAst: SwitchStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.val) {\n preAst.val = walker.walk(preAst.val, preAst);\n }\n\n if ((preAst.caseList) && walker.options.goNextSibling) {\n preAst.caseList = walker.walk(preAst.caseList, preAst);\n }\n }\n\n export function walkTryChildren(preAst: Try, parent: AST, walker: IAstWalker): void {\n if (preAst.body) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkTryCatchChildren(preAst: TryCatch, parent: AST, walker: IAstWalker): void {\n if (preAst.tryNode) {\n preAst.tryNode = walker.walk(preAst.tryNode, preAst);\n }\n\n if ((preAst.catchNode) && walker.options.goNextSibling) {\n preAst.catchNode = walker.walk(preAst.catchNode, preAst);\n }\n }\n\n export function walkTryFinallyChildren(preAst: TryFinally, parent: AST, walker: IAstWalker): void {\n if (preAst.tryNode) {\n preAst.tryNode = walker.walk(preAst.tryNode, preAst);\n }\n\n if (preAst.finallyNode && walker.options.goNextSibling) {\n preAst.finallyNode = walker.walk(preAst.finallyNode, preAst);\n }\n }\n\n export function walkFinallyChildren(preAst: Finally, parent: AST, walker: IAstWalker): void {\n if (preAst.body) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkCatchChildren(preAst: Catch, parent: AST, walker: IAstWalker): void {\n if (preAst.param) {\n preAst.param = walker.walk(preAst.param, preAst);\n }\n\n if ((preAst.body) && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkRecordChildren(preAst: NamedDeclaration, parent: AST, walker: IAstWalker): void {\n preAst.name = walker.walk(preAst.name, preAst);\n if (walker.options.goNextSibling && preAst.members) {\n preAst.members = walker.walk(preAst.members, preAst);\n }\n\n }\n\n export function walkNamedTypeChildren(preAst: TypeDeclaration, parent: AST, walker: IAstWalker): void {\n walkRecordChildren(preAst, parent, walker);\n }\n\n export function walkClassDeclChildren(preAst: ClassDeclaration, parent: AST, walker: IAstWalker): void {\n walkNamedTypeChildren(preAst, parent, walker);\n\n if (walker.options.goNextSibling && preAst.extendsList) {\n preAst.extendsList = walker.walk(preAst.extendsList, preAst);\n }\n\n if (walker.options.goNextSibling && preAst.implementsList) {\n preAst.implementsList = walker.walk(preAst.implementsList, preAst);\n }\n }\n\n export function walkScriptChildren(preAst: Script, parent: AST, walker: IAstWalker): void {\n if (preAst.bod) {\n preAst.bod = walker.walk(preAst.bod, preAst);\n }\n }\n\n export function walkTypeDeclChildren(preAst: InterfaceDeclaration, parent: AST, walker: IAstWalker): void {\n walkNamedTypeChildren(preAst, parent, walker);\n\n // walked arguments as part of members\n if (walker.options.goNextSibling && preAst.extendsList) {\n preAst.extendsList = walker.walk(preAst.extendsList, preAst);\n }\n\n if (walker.options.goNextSibling && preAst.implementsList) {\n preAst.implementsList = walker.walk(preAst.implementsList, preAst);\n }\n }\n\n export function walkModuleDeclChildren(preAst: ModuleDeclaration, parent: AST, walker: IAstWalker): void {\n walkRecordChildren(preAst, parent, walker);\n }\n\n export function walkImportDeclChildren(preAst: ImportDeclaration, parent: AST, walker: IAstWalker): void {\n if (preAst.id) {\n preAst.id = walker.walk(preAst.id, preAst);\n }\n if (preAst.alias) {\n preAst.alias = walker.walk(preAst.alias, preAst);\n }\n }\n\n export function walkWithStatementChildren(preAst: WithStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.expr) {\n preAst.expr = walker.walk(preAst.expr, preAst);\n }\n\n if (preAst.body && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkLabelChildren(preAst: Label, parent: AST, walker: IAstWalker): void {\n //TODO: Walk \"id\"?\n }\n\n export function walkLabeledStatementChildren(preAst: LabeledStatement, parent: AST, walker: IAstWalker): void {\n preAst.labels = walker.walk(preAst.labels, preAst);\n if (walker.options.goNextSibling) {\n preAst.stmt = walker.walk(preAst.stmt, preAst);\n }\n }\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\nmodule TypeScript {\n class Base64Format {\n static encodedValues = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n static encode(inValue: number) {\n if (inValue < 64) {\n return encodedValues.charAt(inValue);\n }\n throw TypeError(inValue + \": not a 64 based value\");\n }\n\n static decodeChar(inChar: string) {\n if (inChar.length === 1) {\n return encodedValues.indexOf(inChar);\n } else {\n throw TypeError('\"' + inChar + '\" must have length 1');\n }\n }\n }\n\n export class Base64VLQFormat {\n static encode(inValue: number) {\n // Add a new least significant bit that has the sign of the value.\n // if negative number the least significant bit that gets added to the number has value 1\n // else least significant bit value that gets added is 0\n // eg. -1 changes to binary : 01 [1] => 3\n // +1 changes to binary : 01 [0] => 2\n if (inValue < 0) {\n inValue = ((-inValue) << 1) + 1;\n }\n else {\n inValue = inValue << 1;\n }\n\n // Encode 5 bits at a time starting from least significant bits\n var encodedStr = \"\";\n do {\n var currentDigit = inValue & 31; // 11111\n inValue = inValue >> 5;\n if (inValue > 0) {\n // There are still more digits to decode, set the msb (6th bit)\n currentDigit = currentDigit | 32; \n }\n encodedStr = encodedStr + Base64Format.encode(currentDigit);\n } while (inValue > 0);\n\n return encodedStr;\n }\n\n static decode(inString: string) {\n var result = 0;\n var negative = false;\n\n var shift = 0;\n for (var i = 0; i < inString.length; i++) {\n var byte = Base64Format.decodeChar(inString[i]);\n if (i === 0) {\n // Sign bit appears in the LSBit of the first value\n if ((byte & 1) === 1) {\n negative = true;\n }\n result = (byte >> 1) & 15; // 1111x\n } else {\n result = result | ((byte & 31) << shift); // 11111\n }\n\n shift += (i == 0) ? 4 : 5;\n\n if ((byte & 32) === 32) {\n // Continue\n } else {\n return { value: negative ? -(result) : result, rest: inString.substr(i + 1) };\n }\n }\n\n throw new Error('Base64 value \"' + inString + '\" finished with a continuation bit');\n }\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///\n\nmodule TypeScript {\n export class Binder {\n constructor(public checker: TypeChecker) { }\n \n public resolveBaseTypeLinks(typeLinks: TypeLink[], scope: SymbolScope) {\n var extendsList: Type[] = null;\n if (typeLinks) {\n extendsList = new Type[];\n for (var i = 0, len = typeLinks.length; i < len; i++) {\n extendsList[i] = this.checker.resolveBaseTypeLink(typeLinks[i], scope);\n }\n }\n return extendsList;\n }\n\n public resolveBases(scope: SymbolScope, type: Type) {\n type.extendsList = this.resolveBaseTypeLinks(type.extendsTypeLinks, scope);\n\n var i = 0, len = type.extendsList.length;\n var derivedIsClass = type.isClassInstance();\n for (; i < len; i++) {\n var baseIsClass = type.extendsList[i].isClassInstance();\n if (type.extendsList[i] != this.checker.anyType) {\n var baseRef = type.extendsTypeLinks[i].ast;\n if (derivedIsClass) {\n if (!baseIsClass) {\n this.checker.errorReporter.simpleError(baseRef,\n \"A class may only extend other classes, \" + type.extendsList[i].symbol.fullName() + \" is not a class.\");\n }\n }\n else {\n if (baseIsClass) {\n this.checker.errorReporter.simpleError(baseRef,\n \"An interface may only extend other interfaces, \" + type.extendsList[i].symbol.fullName() + \" is a class.\");\n }\n }\n }\n }\n\n type.implementsList = this.resolveBaseTypeLinks(type.implementsTypeLinks, scope);\n\n if (type.implementsList) {\n for (i = 0, len = type.implementsList.length; i < len; i++) {\n var iface = type.implementsList[i];\n var baseRef = type.implementsTypeLinks[i].ast;\n if (iface.isClassInstance()) {\n if (derivedIsClass) {\n this.checker.errorReporter.simpleError(baseRef,\n \"A class may only implement an interface; \" + iface.symbol.fullName() + \" is a class.\");\n }\n }\n }\n }\n }\n\n public resolveSignatureGroup(signatureGroup: SignatureGroup, scope: SymbolScope, instanceType: Type) {\n var supplyVar = !(signatureGroup.hasImplementation);\n for (var i = 0, len = signatureGroup.signatures.length; i < len; i++) {\n var signature = signatureGroup.signatures[i];\n if (instanceType) {\n signature.returnType.type = instanceType;\n }\n else {\n this.checker.resolveTypeLink(scope, signature.returnType, supplyVar);\n }\n var paramLen = signature.parameters.length;\n for (var j = 0; j < paramLen; j++) {\n this.bindSymbol(scope, signature.parameters[j]);\n }\n if (signature.hasVariableArgList) {\n // check that last parameter has an array type\n var lastParam = signature.parameters[paramLen - 1];\n lastParam.argsOffset = paramLen - 1;\n if (!lastParam.getType().isArray()) {\n this.checker.errorReporter.simpleErrorFromSym(lastParam,\n \"... parameter must have array type\");\n lastParam.parameter.typeLink.type = this.checker.makeArrayType(lastParam.parameter.typeLink.type);\n }\n }\n }\n }\n\n public bindType(scope: SymbolScope, type: Type, instanceType: Type): void {\n if (instanceType) {\n this.bindType(scope, instanceType, null);\n }\n if (type.hasMembers()) {\n var members = type.members;\n var ambientMembers = type.ambientMembers;\n var typeMembers = type.getAllEnclosedTypes(); // REVIEW: Should only be getting exported types?\n var ambientTypeMembers = type.getAllAmbientEnclosedTypes(); // REVIEW: Should only be getting exported types?\n var memberScope = new SymbolTableScope(members, ambientMembers, typeMembers, ambientTypeMembers, type.symbol);\n var agg = new SymbolAggregateScope(type.symbol);\n var prevCurrentModDecl = this.checker.currentModDecl;\n var prevBindStatus = this.checker.inBind;\n agg.addParentScope(memberScope);\n agg.addParentScope(scope);\n if (type.isModuleType()) {\n this.checker.currentModDecl = type.symbol.declAST;\n this.checker.inBind = true;\n }\n if (members) {\n this.bind(agg, type.members.allMembers); // REVIEW: Should only be getting exported types?\n }\n if (typeMembers) {\n this.bind(agg, typeMembers.allMembers);\n }\n if (ambientMembers) {\n this.bind(agg, ambientMembers.allMembers);\n }\n if (ambientTypeMembers) {\n this.bind(agg, ambientTypeMembers.allMembers);\n }\n this.checker.currentModDecl = prevCurrentModDecl;\n this.checker.inBind = prevBindStatus;\n }\n if (type.extendsTypeLinks) {\n this.resolveBases(scope, type);\n }\n if (type.construct) {\n this.resolveSignatureGroup(type.construct, scope, instanceType);\n }\n if (type.call) {\n this.resolveSignatureGroup(type.call, scope, null);\n }\n if (type.index) {\n this.resolveSignatureGroup(type.index, scope, null);\n }\n if (type.elementType) {\n this.bindType(scope, type.elementType, null);\n }\n }\n\n public bindSymbol(scope: SymbolScope, symbol: Symbol) {\n if (!symbol.bound) {\n var prevLocationInfo = this.checker.locationInfo;\n if ((this.checker.units) && (symbol.unitIndex >= 0) && (symbol.unitIndex < this.checker.units.length)) {\n this.checker.locationInfo = this.checker.units[symbol.unitIndex];\n }\n switch (symbol.kind()) {\n case SymbolKind.Type:\n\n if (symbol.flags & SymbolFlags.Bound) {\n break;\n }\n\n var typeSymbol = symbol;\n typeSymbol.flags |= SymbolFlags.Bound;\n\n // Since type collection happens out of order, a dynamic module referenced by an import statement\n // may not yet be in scope when the import symbol is created. In that case, we need to search\n // out the module symbol now\n // Note that we'll also want to do this in resolveTypeMembers, in case the symbol is set outside the\n // context of a given module (E.g., an outer import statement)\n if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {\n var modPath = (typeSymbol.aliasLink.alias).text;\n var modSym = this.checker.findSymbolForDynamicModule(modPath, this.checker.locationInfo.filename, (id) => scope.find(id, false, true));\n if (modSym) {\n typeSymbol.type = modSym.getType();\n }\n }\n\n if (typeSymbol.type && typeSymbol.type != this.checker.gloModType) {\n this.bindType(scope, typeSymbol.type, typeSymbol.instanceType);\n\n // bind expansions on the parent type symbol\n if (typeSymbol.type.isModuleType()) {\n for (var i = 0; i < typeSymbol.expansions.length; i++) {\n this.bindType(scope, typeSymbol.expansions[i], typeSymbol.instanceType);\n }\n }\n }\n break;\n case SymbolKind.Field:\n this.checker.resolveTypeLink(scope, (symbol).field.typeLink,\n false);\n break;\n case SymbolKind.Parameter:\n this.checker.resolveTypeLink(scope,\n (symbol).parameter.typeLink,\n true);\n break;\n }\n this.checker.locationInfo = prevLocationInfo;\n }\n symbol.bound = true;\n }\n\n public bind(scope: SymbolScope, table: IHashTable) {\n table.map(\n (key, sym, binder) => {\n binder.bindSymbol(scope, sym);\n },\n this);\n }\n }\n\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///\n\nmodule TypeScript {\n export class DeclFileWriter {\n public onNewLine = true;\n constructor(private declFile: ITextWriter) {\n }\n\n public Write(s: string) {\n this.declFile.Write(s);\n this.onNewLine = false;\n }\n\n public WriteLine(s: string) {\n this.declFile.WriteLine(s);\n this.onNewLine = true;\n }\n\n public Close() {\n this.declFile.Close();\n }\n }\n\n export class DeclarationEmitter implements AstWalkerWithDetailCallback.AstWalkerDetailCallback {\n private declFile: DeclFileWriter = null;\n private indenter = new Indenter();\n private declarationContainerStack: AST[] = [];\n private isDottedModuleName: bool[] = [];\n private dottedModuleEmit: string;\n private ignoreCallbackAst: AST = null;\n private singleDeclFile: DeclFileWriter = null;\n private varListCount: number = 0;\n\n private getAstDeclarationContainer() {\n return this.declarationContainerStack[this.declarationContainerStack.length - 1];\n }\n\n private emitDottedModuleName() {\n return (this.isDottedModuleName.length == 0) ? false : this.isDottedModuleName[this.isDottedModuleName.length - 1];\n }\n\n constructor (public checker: TypeChecker, public emitOptions: EmitOptions, public errorReporter: ErrorReporter) {\n }\n\n public setDeclarationFile(file: ITextWriter) {\n this.declFile = new DeclFileWriter(file);\n }\n\n public Close() {\n try {\n // Closing files could result in exceptions, report them if they occur\n this.declFile.Close();\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n\n public emitDeclarations(script: TypeScript.Script): void {\n AstWalkerWithDetailCallback.walk(script, this);\n }\n\n private getIndentString(declIndent? = false) {\n if (this.emitOptions.minWhitespace) {\n return \"\";\n }\n else {\n return this.indenter.getIndent();\n }\n }\n\n private emitIndent() {\n this.declFile.Write(this.getIndentString());\n }\n\n private canEmitSignature(declFlags: DeclFlags, canEmitGlobalAmbientDecl?: bool = true, useDeclarationContainerTop?: bool = true) {\n var container: AST;\n if (useDeclarationContainerTop) {\n container = this.getAstDeclarationContainer();\n } else {\n container = this.declarationContainerStack[this.declarationContainerStack.length - 2];\n }\n\n if (container.nodeType == NodeType.ModuleDeclaration && !hasFlag(declFlags, DeclFlags.Exported)) {\n return false;\n }\n\n if (!canEmitGlobalAmbientDecl && container.nodeType == NodeType.Script && hasFlag(declFlags, DeclFlags.Ambient)) {\n return false;\n }\n\n return true;\n }\n\n private canEmitPrePostAstSignature(declFlags: DeclFlags, astWithPrePostCallback: AST, preCallback: bool) {\n if (this.ignoreCallbackAst) {\n CompilerDiagnostics.assert(this.ignoreCallbackAst != astWithPrePostCallback, \"Ignore Callback AST mismatch\");\n this.ignoreCallbackAst = null;\n return false;\n } else if (preCallback &&\n !this.canEmitSignature(declFlags, true, preCallback)) {\n this.ignoreCallbackAst = astWithPrePostCallback;\n return false;\n }\n\n return true;\n }\n\n private getDeclFlagsString(declFlags: DeclFlags, typeString: string) {\n var result = this.getIndentString();\n\n // Accessor strings\n var accessorString = \"\";\n if (hasFlag(declFlags, DeclFlags.GetAccessor)) {\n accessorString = \"get \";\n }\n else if (hasFlag(declFlags, DeclFlags.SetAccessor)) {\n accessorString = \"set \";\n }\n\n // Emit export only for global export statements. The container for this would be dynamic module which is whole file\n var container = this.getAstDeclarationContainer();\n if (container.nodeType == NodeType.ModuleDeclaration &&\n hasFlag((container).modFlags, ModuleFlags.IsWholeFile) &&\n hasFlag(declFlags, DeclFlags.Exported)) {\n result += \"export \";\n }\n\n // Static/public/private/global declare\n if (hasFlag(declFlags, DeclFlags.LocalStatic) || hasFlag(declFlags, DeclFlags.Static)) {\n result += \"static \" + accessorString;\n }\n else {\n if (hasFlag(declFlags, DeclFlags.Private)) {\n result += \"private \" + accessorString;\n }\n else if (hasFlag(declFlags, DeclFlags.Public)) {\n result += \"public \" + accessorString;\n }\n else {\n if (accessorString == \"\") {\n result += typeString + \" \";\n } else {\n result += accessorString;\n }\n }\n }\n\n return result;\n }\n\n private emitDeclFlags(declFlags: DeclFlags, typeString: string) {\n this.declFile.Write(this.getDeclFlagsString(declFlags, typeString));\n }\n\n private canEmitTypeAnnotationSignature(declFlag: DeclFlags = DeclFlags.None) {\n // Private declaration, shouldnt emit type any time.\n return !hasFlag(declFlag, DeclFlags.Private);\n }\n\n private pushDeclarationContainer(ast: AST) {\n this.declarationContainerStack.push(ast);\n }\n\n private popDeclarationContainer(ast: AST) {\n CompilerDiagnostics.assert(ast != this.getAstDeclarationContainer(), 'Declaration container mismatch');\n this.declarationContainerStack.pop();\n }\n\n private emitTypeNamesMember(memberName: MemberName, emitIndent? : bool = false) {\n if (memberName.prefix == \"{ \") {\n if (emitIndent) {\n this.emitIndent();\n }\n this.declFile.WriteLine(\"{\");\n this.indenter.increaseIndent();\n emitIndent = true;\n } else if (memberName.prefix != \"\") {\n if (emitIndent) {\n this.emitIndent();\n }\n this.declFile.Write(memberName.prefix);\n emitIndent = false;\n }\n\n if (memberName.isString()) {\n if (emitIndent) {\n this.emitIndent();\n }\n this.declFile.Write((memberName).text);\n } else {\n var ar = memberName;\n for (var index = 0; index < ar.entries.length; index++) {\n this.emitTypeNamesMember(ar.entries[index], emitIndent);\n if (ar.delim == \"; \") {\n this.declFile.WriteLine(\";\");\n }\n }\n }\n\n if (memberName.suffix == \"}\") {\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.declFile.Write(memberName.suffix);\n } else {\n this.declFile.Write(memberName.suffix);\n }\n }\n\n private emitTypeSignature(type: Type) {\n var containingScope: SymbolScope = null;\n var declarationContainerAst = this.getAstDeclarationContainer();\n switch (declarationContainerAst.nodeType) {\n case NodeType.ModuleDeclaration:\n case NodeType.InterfaceDeclaration:\n case NodeType.FuncDecl:\n if (declarationContainerAst.type) {\n containingScope = declarationContainerAst.type.containedScope;\n }\n break;\n\n case NodeType.Script:\n var script =