blob: bf5ff169432199a8ab65a0f3d2efa6f9c4af87d1 [file] [log] [blame]
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=\" + (<any>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///<reference path='typescript.ts' />\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 <TypeScript.AST>AstPath.reverseIndexOf(this.asts, this.asts.length - (this.top + 1));\n }\n\n public parent() {\n return <TypeScript.AST>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 ((<TypeScript.InterfaceDeclaration>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 ((<TypeScript.InterfaceDeclaration>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 ((<TypeScript.ArgDecl>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 ((<TypeScript.VarDecl>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 ((<TypeScript.ModuleDeclaration>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 ((<TypeScript.FuncDecl>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 ((<TypeScript.FuncDecl>this.asts[this.top - 2]).isConstructor) &&\n ((<TypeScript.FuncDecl>this.asts[this.top - 2]).arguments === this.asts[this.top - 1]) &&\n ((<TypeScript.ClassDeclaration>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((<TypeScript.ModuleDeclaration>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 (<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0] &&\n TypeScript.hasFlag((<TypeScript.ModuleDeclaration>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 (<TypeScript.Script>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 (<TypeScript.SwitchStatement>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 (<TypeScript.ModuleDeclaration>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 (<TypeScript.ClassDeclaration>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 (<TypeScript.FuncDecl>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 (<TypeScript.InterfaceDeclaration>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 (<TypeScript.Block>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 (<TypeScript.ForStatement>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 (<TypeScript.CaseStatement>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 (<TypeScript.Try>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 (<TypeScript.Catch>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 (<TypeScript.DoWhileStatement>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 (<TypeScript.WhileStatement>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 (<TypeScript.ForInStatement>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 (<TypeScript.WithStatement>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 (<TypeScript.Finally>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 (<TypeScript.SwitchStatement>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 (<TypeScript.SwitchStatement>this.asts[this.top - 2]).caseList == this.asts[this.top - 1] &&\n (<TypeScript.SwitchStatement>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 (<TypeScript.UnaryExpression>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 (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0] &&\n (<TypeScript.ASTList>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 (<TypeScript.UnaryExpression>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 (<TypeScript.UnaryExpression>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 (<TypeScript.UnaryExpression>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 (<TypeScript.BinaryExpression>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 (<TypeScript.BinaryExpression>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 //(<Tools.ASTList>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 (<TypeScript.IfStatement>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 (<TypeScript.IfStatement>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 (<TypeScript.ASTList>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 (<TypeScript.FuncDecl>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 (<TypeScript.FuncDecl>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 (<TypeScript.CallExpression>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 (<TypeScript.CallExpression>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 (<TypeScript.Block>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///<reference path='typescript.ts' />\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 (<any>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 (<any>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 = <ASTList>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(), (<IdentifierToken>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(<ASTList>this.operand);\n break;\n case NodeType.ArrayLit:\n emitter.emitArrayLiteral(<ASTList>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(<Identifier>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 && (<FuncDecl>this.operand2).isAccessor()) {\n var funcDecl = <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 = <ModuleType>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 && !(<TypeSymbol>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 (<Identifier>aliasAST).actualText;\n } else {\n var dotExpr = <BinaryExpression>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 (<Identifier>this.alias).actualText;\n }\n else {\n var dotExpr = <BinaryExpression>this.alias;\n var firstMod = <Identifier>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((<ModuleDeclaration>stmt).modFlags, ModuleFlags.ShouldEmitModuleDecl | ModuleFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.ClassDeclaration) {\n if (!hasFlag((<ClassDeclaration>stmt).varFlags, VarFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.VarDecl) {\n if (!hasFlag((<VarDecl>stmt).varFlags, VarFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.FuncDecl) {\n if (!(<FuncDecl>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 (<BoundDecl>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 = <ASTList>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 = <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 = (<IfStatement>singleItem).cond;\n if (cond.nodeType == NodeType.Call) {\n var target = (<CallExpression>cond).target;\n if (target.nodeType == NodeType.Dot) {\n var binex = <BinaryExpression>target;\n if ((binex.operand1.nodeType == NodeType.Name) &&\n (this.obj.nodeType == NodeType.Name) &&\n ((<Identifier>binex.operand1).actualText == (<Identifier>this.obj).actualText)) {\n var prop = <Identifier>binex.operand2;\n if (prop.actualText == \"hasOwnProperty\") {\n var args = (<CallExpression>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 (((<Identifier>this.lval).actualText) == (<Identifier>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((<ASTList>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 = <CaseStatement>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 = <Finally>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 = <Try>typeFlow.typeCheck(this.tryNode);\n this.catchNode = <Catch>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 = <VarDecl>typeFlow.typeCheck(this.param);\n var exceptVar = new ValueLocation();\n var varSym = new VariableSymbol((<VarDecl>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 (<any>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///<reference path='typescript.ts' />\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 = (<any>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///<reference path='typescript.ts' />\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 (<any>NodeType)._map) {\n if ((<any>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 = <ASTList> 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 = <Identifier>walker.walk(preAst.name, preAst);\n }\n if (preAst.arguments && (preAst.arguments.members.length > 0) && (walker.options.goNextSibling)) {\n preAst.arguments = <ASTList>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 = <ASTList>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 = <Identifier>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 = <ASTList>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 = <ASTList>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 = <ASTList>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 = <Try>walker.walk(preAst.tryNode, preAst);\n }\n\n if ((preAst.catchNode) && walker.options.goNextSibling) {\n preAst.catchNode = <Catch>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 = <Finally>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 = <VarDecl>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 = <Identifier>walker.walk(preAst.name, preAst);\n if (walker.options.goNextSibling && preAst.members) {\n preAst.members = <ASTList>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 = <ASTList>walker.walk(preAst.extendsList, preAst);\n }\n\n if (walker.options.goNextSibling && preAst.implementsList) {\n preAst.implementsList = <ASTList>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 = <ASTList>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 = <ASTList>walker.walk(preAst.extendsList, preAst);\n }\n\n if (walker.options.goNextSibling && preAst.implementsList) {\n preAst.implementsList = <ASTList>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 = <Identifier>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 = <ASTList>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///<reference path='typescript.ts' />\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 = <ParameterSymbol>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 = <ModuleDeclaration>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 = <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 = (<Identifier>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, (<FieldSymbol>symbol).field.typeLink,\n false);\n break;\n case SymbolKind.Parameter:\n this.checker.resolveTypeLink(scope,\n (<ParameterSymbol>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///<reference path='typescript.ts' />\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((<ModuleDeclaration>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((<MemberNameString>memberName).text);\n } else {\n var ar = <MemberNameArray>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 = <Script>declarationContainerAst;\n if (script.bod) {\n containingScope = script.bod.enclosingScope;\n }\n break;\n\n case NodeType.ClassDeclaration:\n if (declarationContainerAst.type) {\n containingScope = declarationContainerAst.type.instanceType.containedScope;\n }\n break;\n\n default:\n CompilerDiagnostics.debugPrint(\"Unknown containing scope\");\n }\n\n var typeNameMembers = type.getScopedTypeNameEx(containingScope);\n this.emitTypeNamesMember(typeNameMembers);\n }\n\n private emitComment(comment: Comment) {\n var text = comment.getText();\n if (this.declFile.onNewLine) {\n this.emitIndent();\n } else if (!comment.isBlockComment) {\n this.declFile.WriteLine(\"\");\n this.emitIndent();\n }\n \n this.declFile.Write(text[0]);\n\n for (var i = 1; i < text.length; i++) {\n this.declFile.WriteLine(\"\");\n this.emitIndent();\n this.declFile.Write(text[i]);\n }\n\n if (comment.endsLine || !comment.isBlockComment) {\n this.declFile.WriteLine(\"\");\n } else {\n this.declFile.Write(\" \");\n }\n }\n\n private emitDeclarationComments(ast: AST, endLine?: bool);\n private emitDeclarationComments(symbol: Symbol, endLine?: bool);\n private emitDeclarationComments(astOrSymbol, endLine = true) {\n if (!this.emitOptions.emitComments) {\n return;\n }\n\n var declComments = <Comment[]>astOrSymbol.getDocComments();\n if (declComments.length > 0) {\n for (var i = 0; i < declComments.length; i++) {\n this.emitComment(declComments[i]);\n }\n\n if (endLine) {\n if (!this.declFile.onNewLine) {\n this.declFile.WriteLine(\"\");\n }\n } else {\n if (this.declFile.onNewLine) {\n this.emitIndent();\n }\n }\n }\n }\n\n public VarDeclCallback(pre: bool, varDecl: VarDecl): bool {\n if (pre && this.canEmitSignature(ToDeclFlags(varDecl.varFlags), false)) {\n var interfaceMember = (this.getAstDeclarationContainer().nodeType == NodeType.InterfaceDeclaration);\n this.emitDeclarationComments(varDecl);\n if (!interfaceMember) {\n // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var\n // If it is var list of form var a = varList count will be 0\n if (this.varListCount >= 0) {\n this.emitDeclFlags(ToDeclFlags(varDecl.varFlags), \"var\");\n this.varListCount = -this.varListCount;\n }\n this.declFile.Write(varDecl.id.text);\n } else {\n this.emitIndent();\n this.declFile.Write(varDecl.id.text);\n if (hasFlag(varDecl.id.flags, ASTFlags.OptionalName)) {\n this.declFile.Write(\"?\");\n }\n }\n\n var type: Type = null;\n if (varDecl.typeExpr && varDecl.typeExpr.type) {\n type = varDecl.typeExpr.type;\n }\n else if (varDecl.sym) {\n type = (<FieldSymbol>varDecl.sym).getType();\n // Dont emit inferred any\n if (type == this.checker.anyType) {\n type = null;\n }\n }\n\n if (type && this.canEmitTypeAnnotationSignature(ToDeclFlags(varDecl.varFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(type);\n }\n \n // emitted one var decl\n if (this.varListCount > 0) { this.varListCount--; } else if (this.varListCount < 0) { this.varListCount++; }\n\n // Write ; or ,\n if (this.varListCount < 0) {\n this.declFile.Write(\", \");\n } else {\n this.declFile.WriteLine(\";\");\n }\n }\n return false;\n }\n\n public BlockCallback(pre: bool, block: Block): bool {\n if (!block.isStatementBlock) {\n if (pre) {\n this.varListCount = block.statements.members.length;\n } else {\n this.varListCount = 0;\n }\n return true;\n }\n return false;\n }\n\n private emitArgDecl(argDecl: ArgDecl, funcDecl: FuncDecl) {\n this.emitDeclarationComments(argDecl, false);\n this.declFile.Write(argDecl.id.text);\n if (argDecl.isOptionalArg()) {\n this.declFile.Write(\"?\");\n }\n if ((argDecl.typeExpr || argDecl.type != this.checker.anyType) &&\n this.canEmitTypeAnnotationSignature(ToDeclFlags(funcDecl.fncFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(argDecl.type);\n }\n }\n\n public FuncDeclCallback(pre: bool, funcDecl: FuncDecl): bool {\n if (!pre) {\n return false;\n }\n\n if (funcDecl.isAccessor()) {\n return this.emitPropertyAccessorSignature(funcDecl);\n }\n\n var isInterfaceMember = (this.getAstDeclarationContainer().nodeType == NodeType.InterfaceDeclaration);\n if (funcDecl.bod) {\n if (funcDecl.isConstructor) {\n if (funcDecl.type.construct && funcDecl.type.construct.signatures.length > 1) {\n return false;\n }\n } else {\n if (funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {\n // This means its implementation of overload signature. do not emit\n return false;\n }\n }\n } else if (!isInterfaceMember && hasFlag(funcDecl.fncFlags, FncFlags.Private) && funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {\n // Print only first overload of private function\n var signatures = funcDecl.type.call.signatures;\n var firstSignature = signatures[0].declAST;\n if (firstSignature.bod) {\n // Its a implementation, use next one\n firstSignature = signatures[1].declAST;\n }\n\n if (firstSignature != funcDecl) {\n return false;\n }\n }\n\n if (!this.canEmitSignature(ToDeclFlags(funcDecl.fncFlags), false)) {\n return false;\n }\n\n this.emitDeclarationComments(funcDecl);\n if (funcDecl.isConstructor) {\n this.emitIndent();\n this.declFile.Write(\"constructor\");\n }\n else {\n var id = funcDecl.getNameText();\n if (!isInterfaceMember) {\n this.emitDeclFlags(ToDeclFlags(funcDecl.fncFlags), \"function\");\n this.declFile.Write(id);\n } else {\n this.emitIndent();\n if (funcDecl.isConstructMember()) {\n this.declFile.Write(\"new\");\n } else if (!funcDecl.isCallMember() && !funcDecl.isIndexerMember()) {\n this.declFile.Write(id);\n if (hasFlag(funcDecl.name.flags, ASTFlags.OptionalName)) {\n this.declFile.Write(\"? \");\n }\n }\n }\n }\n\n if (!funcDecl.isIndexerMember()) {\n this.declFile.Write(\"(\");\n } else {\n this.declFile.Write(\"[\");\n }\n\n this.indenter.increaseIndent();\n\n if (funcDecl.arguments) {\n var argsLen = funcDecl.arguments.members.length;\n if (funcDecl.variableArgList) {\n argsLen--;\n }\n for (var i = 0; i < argsLen; i++) {\n var argDecl = <ArgDecl>funcDecl.arguments.members[i];\n this.emitArgDecl(argDecl, funcDecl);\n if (i < (argsLen - 1)) {\n this.declFile.Write(\", \");\n }\n }\n }\n\n if (funcDecl.variableArgList) {\n var lastArg = <ArgDecl>funcDecl.arguments.members[funcDecl.arguments.members.length - 1];\n if (funcDecl.arguments.members.length > 1) {\n this.declFile.Write(\", ...\");\n }\n else {\n this.declFile.Write(\"...\");\n }\n this.emitArgDecl(lastArg, funcDecl);\n }\n\n this.indenter.decreaseIndent();\n\n if (!funcDecl.isIndexerMember()) {\n this.declFile.Write(\")\");\n } else {\n this.declFile.Write(\"]\");\n }\n\n if (!funcDecl.isConstructor &&\n (funcDecl.returnTypeAnnotation || funcDecl.signature.returnType.type != this.checker.anyType) &&\n this.canEmitTypeAnnotationSignature(ToDeclFlags(funcDecl.fncFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(funcDecl.signature.returnType.type);\n }\n\n this.declFile.WriteLine(\";\");\n\n return false;\n }\n\n private emitBaseList(bases: ASTList, qual: string) {\n if (bases && (bases.members.length > 0)) {\n this.declFile.Write(\" \" + qual + \" \");\n var basesLen = bases.members.length;\n for (var i = 0; i < basesLen; i++) {\n var baseExpr = bases.members[i];\n var baseSymbol = baseExpr.type.symbol;\n var baseType = baseExpr.type;\n if (i > 0) {\n this.declFile.Write(\", \");\n }\n this.emitTypeSignature(baseType);\n }\n }\n }\n\n private emitPropertyAccessorSignature(funcDecl: FuncDecl) {\n var accessorSymbol = <FieldSymbol>funcDecl.accessorSymbol;\n if (accessorSymbol.getter && accessorSymbol.getter.declAST != funcDecl) {\n // Setter is being used to emit the type info. \n return false;\n }\n\n this.emitDeclarationComments(accessorSymbol);\n this.emitDeclFlags(ToDeclFlags(accessorSymbol.flags), \"var\");\n this.declFile.Write(funcDecl.name.text);\n var propertyType = accessorSymbol.getType();\n if (this.canEmitTypeAnnotationSignature(ToDeclFlags(accessorSymbol.flags))) {\n this.declFile.Write(\" : \");\n this.emitTypeSignature(propertyType);\n }\n this.declFile.WriteLine(\";\");\n\n return false;\n }\n\n private emitClassMembersFromConstructorDefinition(funcDecl: FuncDecl) {\n if (funcDecl.arguments) {\n var argsLen = funcDecl.arguments.members.length; if (funcDecl.variableArgList) { argsLen--; }\n\n for (var i = 0; i < argsLen; i++) {\n var argDecl = <ArgDecl>funcDecl.arguments.members[i];\n if (hasFlag(argDecl.varFlags, VarFlags.Property)) {\n this.emitDeclarationComments(argDecl);\n this.emitDeclFlags(ToDeclFlags(argDecl.varFlags), \"var\");\n this.declFile.Write(argDecl.id.text);\n\n if (argDecl.typeExpr && this.canEmitTypeAnnotationSignature(ToDeclFlags(argDecl.varFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(argDecl.type);\n }\n this.declFile.WriteLine(\";\");\n }\n }\n }\n }\n\n public ClassDeclarationCallback(pre: bool, classDecl: ClassDeclaration): bool {\n if (!this.canEmitPrePostAstSignature(ToDeclFlags(classDecl.varFlags), classDecl, pre)) {\n return false;\n }\n\n if (pre) {\n var className = classDecl.name.text;\n this.emitDeclarationComments(classDecl);\n this.emitDeclFlags(ToDeclFlags(classDecl.varFlags), \"class\");\n this.declFile.Write(className);\n this.emitBaseList(classDecl.extendsList, \"extends\");\n this.emitBaseList(classDecl.implementsList, \"implements\");\n this.declFile.WriteLine(\" {\");\n\n this.pushDeclarationContainer(classDecl);\n this.indenter.increaseIndent();\n if (classDecl.constructorDecl) {\n this.emitClassMembersFromConstructorDefinition(classDecl.constructorDecl);\n }\n } else {\n this.indenter.decreaseIndent();\n this.popDeclarationContainer(classDecl);\n\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n }\n\n return true;\n }\n\n public InterfaceDeclarationCallback(pre: bool, interfaceDecl: InterfaceDeclaration): bool {\n if (!this.canEmitPrePostAstSignature(ToDeclFlags(interfaceDecl.varFlags), interfaceDecl, pre)) {\n return false;\n }\n\n if (pre) {\n var interfaceName = interfaceDecl.name.text;\n this.emitDeclarationComments(interfaceDecl);\n this.emitDeclFlags(ToDeclFlags(interfaceDecl.varFlags), \"interface\");\n this.declFile.Write(interfaceName);\n this.emitBaseList(interfaceDecl.extendsList, \"extends\");\n this.declFile.WriteLine(\" {\");\n\n this.indenter.increaseIndent();\n this.pushDeclarationContainer(interfaceDecl);\n } else {\n this.indenter.decreaseIndent();\n this.popDeclarationContainer(interfaceDecl);\n\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n }\n\n return true;\n }\n\n public ImportDeclarationCallback(pre: bool, importDecl: ImportDeclaration): bool {\n if (pre) {\n if ((<Script>this.declarationContainerStack[0]).isExternallyVisibleSymbol(importDecl.id.sym)) {\n this.emitDeclarationComments(importDecl);\n this.emitIndent();\n this.declFile.Write(\"import \");\n\n this.declFile.Write(importDecl.id.text + \" = \");\n if (importDecl.isDynamicImport) {\n this.declFile.WriteLine(\"module (\" + importDecl.getAliasName() + \");\");\n } else {\n this.declFile.WriteLine(importDecl.getAliasName() + \";\");\n }\n }\n }\n\n return false;\n }\n\n private emitEnumSignature(moduleDecl: ModuleDeclaration) {\n if (!this.canEmitSignature(ToDeclFlags(moduleDecl.modFlags))) {\n return false;\n }\n\n this.emitDeclarationComments(moduleDecl);\n this.emitDeclFlags(ToDeclFlags(moduleDecl.modFlags), \"enum\");\n this.declFile.WriteLine(moduleDecl.name.text + \" {\");\n\n this.indenter.increaseIndent();\n var membersLen = moduleDecl.members.members.length;\n for (var j = 1; j < membersLen; j++) {\n var memberDecl: AST = moduleDecl.members.members[j];\n if (memberDecl.nodeType == NodeType.VarDecl) {\n this.emitDeclarationComments(memberDecl);\n this.emitIndent();\n this.declFile.WriteLine((<VarDecl>memberDecl).id.text + \",\");\n } else {\n CompilerDiagnostics.assert(memberDecl.nodeType != NodeType.Asg, \"We want to catch this\");\n }\n }\n this.indenter.decreaseIndent();\n\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n\n return false;\n }\n\n public ModuleDeclarationCallback(pre: bool, moduleDecl: ModuleDeclaration): bool {\n if (hasFlag(moduleDecl.modFlags, ModuleFlags.IsWholeFile)) {\n // This is dynamic modules and we are going to outputing single file, \n // we need to change the declFile because dynamic modules are always emitted to their corresponding .d.ts\n if (hasFlag(moduleDecl.modFlags, ModuleFlags.IsDynamic)) {\n if (pre) {\n if (!this.emitOptions.outputMany) {\n this.singleDeclFile = this.declFile;\n CompilerDiagnostics.assert(this.indenter.indentAmt == 0, \"Indent has to be 0 when outputing new file\");\n // Create new file\n var declareFileName = this.emitOptions.mapOutputFileName(stripQuotes(moduleDecl.name.sym.name), TypeScriptCompiler.mapToDTSFileName);\n var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);\n try {\n // Creating files can cause exceptions, report them. \n this.declFile = new DeclFileWriter(this.emitOptions.ioHost.createFile(declareFileName, useUTF8InOutputfile));\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n this.pushDeclarationContainer(moduleDecl);\n } else {\n if (!this.emitOptions.outputMany) {\n CompilerDiagnostics.assert(this.singleDeclFile != this.declFile, \"singleDeclFile cannot be null as we are going to revert back to it\");\n CompilerDiagnostics.assert(this.indenter.indentAmt == 0, \"Indent has to be 0 when outputing new file\");\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 this.declFile = this.singleDeclFile;\n }\n this.popDeclarationContainer(moduleDecl);\n }\n }\n\n return true;\n }\n\n if (moduleDecl.isEnum()) {\n if (pre) {\n this.emitEnumSignature(moduleDecl);\n }\n return false;\n }\n\n if (!this.canEmitPrePostAstSignature(ToDeclFlags(moduleDecl.modFlags), moduleDecl, pre)) {\n return false;\n }\n\n if (pre) {\n if (this.emitDottedModuleName()) {\n this.dottedModuleEmit += \".\";\n } else {\n this.dottedModuleEmit = this.getDeclFlagsString(ToDeclFlags(moduleDecl.modFlags), \"module\");\n }\n this.dottedModuleEmit += moduleDecl.name.text;\n\n var isCurrentModuleDotted = (moduleDecl.members.members.length == 1 &&\n moduleDecl.members.members[0].nodeType == NodeType.ModuleDeclaration &&\n !(<ModuleDeclaration>moduleDecl.members.members[0]).isEnum() &&\n hasFlag((<ModuleDeclaration>moduleDecl.members.members[0]).modFlags, ModuleFlags.Exported));\n\n // Module is dotted only if it does not have doc comments for it\n var moduleDeclComments = moduleDecl.getDocComments();\n isCurrentModuleDotted = isCurrentModuleDotted && (moduleDeclComments == null || moduleDeclComments.length == 0);\n\n this.isDottedModuleName.push(isCurrentModuleDotted);\n this.pushDeclarationContainer(moduleDecl);\n\n if (!isCurrentModuleDotted) {\n this.emitDeclarationComments(moduleDecl);\n this.declFile.Write(this.dottedModuleEmit);\n this.declFile.WriteLine(\" {\");\n this.indenter.increaseIndent();\n }\n } else {\n if (!this.emitDottedModuleName()) {\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n }\n this.popDeclarationContainer(moduleDecl);\n this.isDottedModuleName.pop();\n }\n\n return true;\n }\n\n public ScriptCallback(pre: bool, script: Script): bool {\n if (pre) {\n if (this.emitOptions.outputMany) {\n for (var i = 0; i < script.referencedFiles.length; i++) {\n var referencePath = script.referencedFiles[i].path;\n var declareFileName: string;\n if (isRooted(referencePath)) {\n declareFileName = this.emitOptions.mapOutputFileName(referencePath, TypeScriptCompiler.mapToDTSFileName)\n } else {\n declareFileName = getDeclareFilePath(script.referencedFiles[i].path);\n }\n this.declFile.WriteLine('/// <reference path=\"' + declareFileName + '\" />');\n }\n }\n this.pushDeclarationContainer(script);\n }\n else {\n this.popDeclarationContainer(script);\n }\n return true;\n }\n\n public DefaultCallback(pre: bool, ast: AST): bool {\n return !hasFlag(ast.flags, ASTFlags.IsStatement);\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export module CompilerDiagnostics {\n export var debug = false;\n export interface IDiagnosticWriter {\n Alert(output: string): void;\n }\n\n export var diagnosticWriter: IDiagnosticWriter = null;\n\n export var analysisPass: number = 0;\n\n export function Alert(output: string) {\n if (diagnosticWriter) {\n diagnosticWriter.Alert(output);\n }\n }\n\n export function debugPrint(s: string) {\n if (debug) {\n Alert(s);\n }\n }\n\n export function assert(condition: bool, s: string) {\n if (debug) {\n if (!condition) {\n Alert(s);\n }\n }\n }\n\n }\n\n export interface ILogger {\n information(): bool;\n debug(): bool;\n warning(): bool;\n error(): bool;\n fatal(): bool;\n log(s: string): void;\n }\n\n export class NullLogger implements ILogger {\n public information(): bool { return false; }\n public debug(): bool { return false; }\n public warning(): bool { return false; }\n public error(): bool { return false; }\n public fatal(): bool { return false; }\n public log(s: string): void {\n }\n }\n\n export class LoggerAdapter implements ILogger {\n private _information: bool;\n private _debug: bool;\n private _warning: bool;\n private _error: bool;\n private _fatal: bool;\n\n constructor (public logger: ILogger) { \n this._information = this.logger.information();\n this._debug = this.logger.debug();\n this._warning = this.logger.warning();\n this._error = this.logger.error();\n this._fatal = this.logger.fatal();\n }\n\n\n public information(): bool { return this._information; }\n public debug(): bool { return this._debug; }\n public warning(): bool { return this._warning; }\n public error(): bool { return this._error; }\n public fatal(): bool { return this._fatal; }\n public log(s: string): void {\n this.logger.log(s);\n }\n }\n\n export class BufferedLogger implements ILogger {\n public logContents = [];\n\n public information(): bool { return false; }\n public debug(): bool { return false; }\n public warning(): bool { return false; }\n public error(): bool { return false; }\n public fatal(): bool { return false; }\n public log(s: string): void {\n this.logContents.push(s);\n }\n }\n\n export function timeFunction(logger: ILogger, funcDescription: string, func: () =>any): any {\n var start = +new Date();\n var result = func();\n var end = +new Date();\n logger.log(funcDescription + \" completed in \" + (end - start) + \" msec\");\n return result;\n }\n\n export function stringToLiteral(value: string, length: number): string {\n var result = \"\";\n\n var addChar = (index: number) => {\n var ch = value.charCodeAt(index);\n switch (ch) {\n case 0x09: // tab\n result += \"\\\\t\";\n break;\n case 0x0a: // line feed\n result += \"\\\\n\";\n break;\n case 0x0b: // vertical tab\n result += \"\\\\v\";\n break;\n case 0x0c: // form feed\n result += \"\\\\f\";\n break;\n case 0x0d: // carriage return\n result += \"\\\\r\";\n break;\n case 0x22: // double quote\n result += \"\\\\\\\"\";\n break;\n case 0x27: // single quote\n result += \"\\\\\\'\";\n break;\n case 0x5c: // Backslash\n result += \"\\\\\";\n break;\n default:\n result += value.charAt(index);\n }\n }\n\n var tooLong = (value.length > length);\n if (tooLong) {\n var mid = length >> 1;\n for (var i = 0; i < mid; i++) addChar(i);\n result += \"(...)\";\n for (var i = value.length - mid; i < value.length; i++) addChar(i);\n }\n else {\n length = value.length;\n for (var i = 0; i < length; i++) addChar(i);\n }\n return result;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export enum EmitContainer {\n Prog,\n Module,\n DynamicModule,\n Class,\n Constructor,\n Function,\n Args,\n Interface,\n }\n\n export class EmitState {\n public column: number;\n public line: number;\n public pretty: bool;\n public inObjectLiteral: bool;\n public container: EmitContainer;\n\n constructor () {\n this.column = 0;\n this.line = 0;\n this.pretty = false;\n this.inObjectLiteral = false;\n this.container = EmitContainer.Prog;\n }\n }\n\n export class EmitOptions {\n public minWhitespace: bool;\n public propagateConstants: bool;\n public emitComments: bool;\n public outputOption: string;\n public ioHost: EmitterIOHost = null;\n public outputMany: bool = true;\n public commonDirectoryPath = \"\";\n\n constructor(settings: CompilationSettings) {\n this.minWhitespace = settings.minWhitespace;\n this.propagateConstants = settings.propagateConstants;\n this.emitComments = settings.emitComments;\n this.outputOption = settings.outputOption;\n }\n\n public mapOutputFileName(fileName: string, extensionChanger: (fname: string, wholeFileNameReplaced: bool) => string) {\n if (this.outputMany) {\n var updatedFileName = fileName;\n if (this.outputOption != \"\") {\n // Replace the common directory path with the option specified\n updatedFileName = fileName.replace(this.commonDirectoryPath, \"\");\n updatedFileName = this.outputOption + updatedFileName;\n }\n return extensionChanger(updatedFileName, false);\n } else {\n return extensionChanger(this.outputOption, true);\n }\n }\n }\n\n export class Indenter {\n static indentStep : number = 4;\n static indentStepString : string = \" \";\n static indentStrings: string[] = [];\n public indentAmt: number = 0;\n\n public increaseIndent() {\n this.indentAmt += Indenter.indentStep;\n }\n\n public decreaseIndent() {\n this.indentAmt -= Indenter.indentStep;\n }\n\n public getIndent() {\n var indentString = Indenter.indentStrings[this.indentAmt];\n if (indentString === undefined) {\n indentString = \"\";\n for (var i = 0; i < this.indentAmt; i = i + Indenter.indentStep) {\n indentString += Indenter.indentStepString;\n }\n Indenter.indentStrings[this.indentAmt] = indentString;\n }\n return indentString;\n }\n }\n\n export class Emitter {\n public prologueEmitted = false;\n public thisClassNode: TypeDeclaration = null;\n public thisFnc: FuncDecl = null;\n public moduleDeclList: ModuleDeclaration[] = [];\n public moduleName = \"\";\n public emitState = new EmitState();\n public indenter = new Indenter();\n public ambientModule = false;\n public modAliasId: string = null;\n public firstModAlias: string = null;\n public allSourceMappers: SourceMapper[] = [];\n public sourceMapper: SourceMapper = null;\n public captureThisStmtString = \"var _this = this;\";\n private varListCountStack: number[] = [0]; \n\n constructor(public checker: TypeChecker, public emittingFileName: string, public outfile: ITextWriter, public emitOptions: EmitOptions, public errorReporter: ErrorReporter) {\n }\n\n public setSourceMappings(mapper: SourceMapper) {\n this.allSourceMappers.push(mapper);\n this.sourceMapper = mapper;\n }\n\n public writeToOutput(s: string) {\n this.outfile.Write(s);\n // TODO: check s for newline\n this.emitState.column += s.length;\n }\n\n public writeToOutputTrimmable(s: string) {\n if (this.emitOptions.minWhitespace) {\n s = s.replace(/[\\s]*/g, '');\n }\n this.writeToOutput(s);\n }\n\n public writeLineToOutput(s: string) {\n if (this.emitOptions.minWhitespace) {\n this.writeToOutput(s);\n var c = s.charCodeAt(s.length - 1);\n if (!((c == LexCodeSpace) || (c == LexCodeSMC) || (c == LexCodeLBR))) {\n this.writeToOutput(' ');\n }\n }\n else {\n this.outfile.WriteLine(s);\n this.emitState.column = 0\n this.emitState.line++;\n }\n }\n\n public writeCaptureThisStatement(ast: AST) {\n this.emitIndent();\n this.recordSourceMappingStart(ast);\n this.writeToOutput(this.captureThisStmtString);\n this.recordSourceMappingEnd(ast);\n this.writeLineToOutput(\"\");\n }\n\n public setInVarBlock(count: number) {\n this.varListCountStack[this.varListCountStack.length - 1] = count;\n }\n\n public setInObjectLiteral(val: bool): bool {\n var temp = this.emitState.inObjectLiteral;\n this.emitState.inObjectLiteral = val;\n return temp;\n }\n\n public setContainer(c: number): number {\n var temp = this.emitState.container;\n this.emitState.container = c;\n return temp;\n }\n\n private getIndentString() {\n if (this.emitOptions.minWhitespace) {\n return \"\";\n }\n else {\n return this.indenter.getIndent();\n }\n }\n\n public emitIndent() {\n this.writeToOutput(this.getIndentString());\n }\n\n public emitCommentInPlace(comment: Comment) {\n var text = comment.getText();\n var hadNewLine = false;\n\n if (comment.isBlockComment) {\n if (this.emitState.column == 0) {\n this.emitIndent();\n }\n this.recordSourceMappingStart(comment);\n this.writeToOutput(text[0]);\n\n if (text.length > 1 || comment.endsLine) {\n for (var i = 1; i < text.length; i++) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n this.writeToOutput(text[i]);\n }\n this.recordSourceMappingEnd(comment);\n this.writeLineToOutput(\"\");\n hadNewLine = true;\n } else {\n this.recordSourceMappingEnd(comment);\n }\n }\n else {\n if (this.emitState.column == 0) {\n this.emitIndent();\n }\n this.recordSourceMappingStart(comment);\n this.writeToOutput(text[0]);\n this.recordSourceMappingEnd(comment);\n this.writeLineToOutput(\"\");\n hadNewLine = true;\n }\n\n if (hadNewLine) {\n this.emitIndent();\n }\n else {\n this.writeToOutput(\" \");\n }\n }\n\n public emitParensAndCommentsInPlace(ast: AST, pre: bool) {\n var comments = pre ? ast.preComments : ast.postComments;\n\n // comments should be printed before the LParen, but after the RParen\n if (ast.isParenthesized && !pre) {\n this.writeToOutput(\")\");\n }\n if (this.emitOptions.emitComments && comments && comments.length != 0) {\n for (var i = 0; i < comments.length; i++) {\n this.emitCommentInPlace(comments[i]);\n }\n }\n if (ast.isParenthesized && pre) {\n this.writeToOutput(\"(\");\n }\n }\n\n // TODO: emit accessor pattern\n public emitObjectLiteral(content: ASTList) {\n this.writeLineToOutput(\"{\");\n this.indenter.increaseIndent();\n var inObjectLiteral = this.setInObjectLiteral(true);\n this.emitJavascriptList(content, \",\", TokenID.Comma, true, false, false);\n this.setInObjectLiteral(inObjectLiteral);\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeToOutput(\"}\");\n }\n\n public emitArrayLiteral(content: ASTList) {\n this.writeToOutput(\"[\");\n if (content) {\n this.writeLineToOutput(\"\");\n this.indenter.increaseIndent();\n this.emitJavascriptList(content, \", \", TokenID.Comma, true, false, false);\n this.indenter.decreaseIndent();\n this.emitIndent();\n }\n this.writeToOutput(\"]\");\n }\n\n public emitNew(target: AST, args: ASTList) {\n this.writeToOutput(\"new \");\n if (target.nodeType == NodeType.TypeRef) {\n var typeRef = <TypeReference>target;\n if (typeRef.arrayCount) {\n this.writeToOutput(\"Array()\");\n }\n else {\n this.emitJavascript(typeRef.term, TokenID.Tilde, false);\n this.writeToOutput(\"()\");\n }\n }\n else {\n this.emitJavascript(target, TokenID.Tilde, false);\n this.recordSourceMappingStart(args);\n this.writeToOutput(\"(\");\n this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n this.writeToOutput(\")\");\n this.recordSourceMappingEnd(args);\n }\n }\n\n public tryEmitConstant(dotExpr: BinaryExpression) {\n if (!this.emitOptions.propagateConstants) {\n return false;\n }\n var propertyName = <Identifier>dotExpr.operand2;\n if (propertyName && propertyName.sym && propertyName.sym.isVariable()) {\n if (hasFlag(propertyName.sym.flags, SymbolFlags.Constant)) {\n if (propertyName.sym.declAST) {\n var boundDecl = <BoundDecl>propertyName.sym.declAST;\n if (boundDecl.init && (boundDecl.init.nodeType == NodeType.NumberLit)) {\n var numLit = <NumberLiteral>boundDecl.init;\n this.writeToOutput(numLit.value.toString());\n var comment = \" /* \";\n comment += propertyName.actualText;\n comment += \" */ \";\n this.writeToOutput(comment);\n return true;\n }\n }\n }\n }\n return false;\n }\n\n public emitCall(callNode: CallExpression, target: AST, args: ASTList) {\n if (!this.emitSuperCall(callNode)) {\n if (!hasFlag(callNode.flags, ASTFlags.ClassBaseConstructorCall)) {\n if (target.nodeType == NodeType.FuncDecl && !target.isParenthesized) {\n this.writeToOutput(\"(\");\n }\n if (callNode.target.nodeType == NodeType.Super && this.emitState.container == EmitContainer.Constructor) {\n this.writeToOutput(\"_super.call\");\n }\n else {\n this.emitJavascript(target, TokenID.OpenParen, false);\n }\n if (target.nodeType == NodeType.FuncDecl && !target.isParenthesized) {\n this.writeToOutput(\")\");\n }\n this.recordSourceMappingStart(args);\n this.writeToOutput(\"(\");\n if (callNode.target.nodeType == NodeType.Super && this.emitState.container == EmitContainer.Constructor) {\n this.writeToOutput(\"this\");\n if (args && args.members.length) {\n this.writeToOutput(\", \");\n }\n }\n this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n this.writeToOutput(\")\");\n this.recordSourceMappingEnd(args);\n }\n else {\n this.indenter.decreaseIndent();\n this.indenter.decreaseIndent();\n var constructorCall = new ASTList();\n constructorCall.members[0] = callNode;\n this.emitConstructorCalls(constructorCall, this.thisClassNode);\n this.indenter.increaseIndent();\n this.indenter.increaseIndent();\n }\n }\n }\n\n public emitConstructorCalls(bases: ASTList, classDecl: TypeDeclaration) {\n if (bases == null) {\n return;\n }\n var basesLen = bases.members.length;\n this.recordSourceMappingStart(classDecl);\n for (var i = 0; i < basesLen; i++) {\n var baseExpr = bases.members[i];\n var baseSymbol: Symbol = null;\n if (baseExpr.nodeType == NodeType.Call) {\n baseSymbol = (<CallExpression>baseExpr).target.type.symbol;\n }\n else {\n baseSymbol = baseExpr.type.symbol;\n }\n var baseName = baseSymbol.name;\n if (baseSymbol.declModule != classDecl.type.symbol.declModule) {\n baseName = baseSymbol.fullName();\n }\n if (baseExpr.nodeType == NodeType.Call) {\n this.emitIndent();\n this.writeToOutput(\"_super.call(this\");\n var args = (<CallExpression>baseExpr).arguments;\n if (args && (args.members.length > 0)) {\n this.writeToOutput(\", \");\n this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n }\n this.writeToOutput(\")\");\n }\n else {\n if (baseExpr.type && (baseExpr.type.isClassInstance())) {\n // parameterless constructor call;\n this.emitIndent();\n this.writeToOutput(classDecl.name.actualText + \"._super.constructor\");\n //emitJavascript(baseExpr,TokenID.LParen,false);\n this.writeToOutput(\".call(this)\");\n }\n }\n }\n this.recordSourceMappingEnd(classDecl);\n }\n\n public emitInnerFunction(funcDecl: FuncDecl, printName: bool, isMember: bool,\n bases: ASTList, hasSelfRef: bool, classDecl: TypeDeclaration) {\n /// REVIEW: The code below causes functions to get pushed to a newline in cases where they shouldn't\n /// such as: \n /// Foo.prototype.bar = \n /// function() {\n /// };\n /// Once we start emitting comments, we should pull this code out to place on the outer context where the function\n /// is used.\n //if (funcDecl.preComments!=null && funcDecl.preComments.length>0) {\n // this.writeLineToOutput(\"\");\n // this.increaseIndent();\n // emitIndent();\n //}\n\n var isClassConstructor = funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod);\n var hasNonObjectBaseType = isClassConstructor && hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeFlags.HasBaseType) && !hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeFlags.HasBaseTypeOfObject);\n var classPropertiesMustComeAfterSuperCall = hasNonObjectBaseType && hasFlag((<ClassDeclaration>this.thisClassNode).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor);\n\n // We have no way of knowing if the current function is used as an expression or a statement, so as to enusre that the emitted\n // JavaScript is always valid, add an extra parentheses for unparenthesized function expressions\n var shouldParenthesize = hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression) && !funcDecl.isParenthesized && !funcDecl.isAccessor() && (hasFlag(funcDecl.flags, ASTFlags.ExplicitSemicolon) || hasFlag(funcDecl.flags, ASTFlags.AutomaticSemicolon));\n\n this.emitParensAndCommentsInPlace(funcDecl, true);\n if (shouldParenthesize) {\n this.writeToOutput(\"(\");\n }\n this.recordSourceMappingStart(funcDecl);\n if (!(funcDecl.isAccessor() && (<FieldSymbol>funcDecl.accessorSymbol).isObjectLitField)) {\n this.writeToOutput(\"function \");\n }\n if (printName) {\n var id = funcDecl.getNameText();\n if (id && !funcDecl.isAccessor()) {\n if (funcDecl.name) {\n this.recordSourceMappingStart(funcDecl.name);\n }\n this.writeToOutput(id);\n if (funcDecl.name) {\n this.recordSourceMappingEnd(funcDecl.name);\n }\n }\n }\n\n this.writeToOutput(\"(\");\n var argsLen = 0;\n var i = 0;\n var arg: ArgDecl;\n var defaultArgs: ArgDecl[] = [];\n if (funcDecl.arguments) {\n var tempContainer = this.setContainer(EmitContainer.Args);\n argsLen = funcDecl.arguments.members.length;\n var printLen = argsLen;\n if (funcDecl.variableArgList) {\n printLen--;\n }\n for (i = 0; i < printLen; i++) {\n arg = <ArgDecl>funcDecl.arguments.members[i];\n if (arg.init) {\n defaultArgs.push(arg);\n }\n this.emitJavascript(arg, TokenID.OpenParen, false);\n if (i < (printLen - 1)) {\n this.writeToOutput(\", \");\n }\n }\n this.setContainer(tempContainer);\n }\n this.writeLineToOutput(\") {\");\n\n if (funcDecl.isConstructor) {\n this.recordSourceMappingNameStart(\"constructor\");\n } else if (funcDecl.isGetAccessor()) {\n this.recordSourceMappingNameStart(\"get_\" + funcDecl.getNameText());\n } else if (funcDecl.isSetAccessor()) {\n this.recordSourceMappingNameStart(\"set_\" + funcDecl.getNameText());\n } else {\n this.recordSourceMappingNameStart(funcDecl.getNameText());\n }\n this.indenter.increaseIndent();\n\n // set default args first\n for (i = 0; i < defaultArgs.length; i++) {\n var arg = defaultArgs[i];\n this.emitIndent();\n this.recordSourceMappingStart(arg);\n this.writeToOutput(\"if (typeof \" + arg.id.actualText + \" === \\\"undefined\\\") { \");//\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeToOutput(\" = \");\n this.emitJavascript(arg.init, TokenID.OpenParen, false);\n this.writeLineToOutput(\"; }\")\n this.recordSourceMappingEnd(arg);\n }\n\n if (funcDecl.isConstructor && ((<ClassDeclaration>funcDecl.classDecl).varFlags & VarFlags.MustCaptureThis)) {\n this.writeCaptureThisStatement(funcDecl);\n }\n\n if (funcDecl.isConstructor && !classPropertiesMustComeAfterSuperCall) {\n if (funcDecl.arguments) {\n argsLen = funcDecl.arguments.members.length;\n for (i = 0; i < argsLen; i++) {\n arg = <ArgDecl>funcDecl.arguments.members[i];\n if ((arg.varFlags & VarFlags.Property) != VarFlags.None) {\n this.emitIndent();\n this.recordSourceMappingStart(arg);\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(\"this.\" + arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeToOutput(\" = \");\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(arg);\n }\n }\n }\n\n // For classes, the constructor needs to be explicitly called\n if (!hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n this.emitConstructorCalls(bases, classDecl);\n }\n }\n if (hasSelfRef) {\n this.writeCaptureThisStatement(funcDecl);\n }\n if (funcDecl.variableArgList) {\n argsLen = funcDecl.arguments.members.length;\n var lastArg = <ArgDecl>funcDecl.arguments.members[argsLen - 1];\n this.emitIndent();\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"var \");\n this.recordSourceMappingStart(lastArg.id);\n this.writeToOutput(lastArg.id.actualText);\n this.recordSourceMappingEnd(lastArg.id);\n this.writeLineToOutput(\" = [];\");\n this.recordSourceMappingEnd(lastArg);\n this.emitIndent();\n this.writeToOutput(\"for (\")\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"var _i = 0;\");\n this.recordSourceMappingEnd(lastArg);\n this.writeToOutput(\" \");\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"_i < (arguments.length - \" + (argsLen - 1) + \")\");\n this.recordSourceMappingEnd(lastArg);\n this.writeToOutput(\"; \");\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"_i++\");\n this.recordSourceMappingEnd(lastArg);\n this.writeLineToOutput(\") {\");\n this.indenter.increaseIndent();\n this.emitIndent();\n\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(lastArg.id.actualText + \"[_i] = arguments[_i + \" + (argsLen - 1) + \"];\");\n this.recordSourceMappingEnd(lastArg);\n this.writeLineToOutput(\"\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeLineToOutput(\"}\");\n }\n\n // if it's a class, emit the uninitializedMembers, first emit the non-proto class body members\n if (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod) && !classPropertiesMustComeAfterSuperCall) {\n\n var nProps = (<ASTList>this.thisClassNode.members).members.length;\n\n for (var i = 0; i < nProps; i++) {\n if ((<ASTList>this.thisClassNode.members).members[i].nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>(<ASTList>this.thisClassNode.members).members[i];\n if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n this.emitIndent();\n this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n this.writeLineToOutput(\"\");\n }\n }\n }\n //this.writeLineToOutput(\"\");\n }\n\n this.emitBareJavascriptStatements(funcDecl.bod, classPropertiesMustComeAfterSuperCall);\n\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl.endingToken);\n this.writeToOutput(\"}\");\n\n this.recordSourceMappingNameEnd();\n this.recordSourceMappingEnd(funcDecl.endingToken);\n this.recordSourceMappingEnd(funcDecl);\n\n if (shouldParenthesize) {\n this.writeToOutput(\")\");\n }\n\n // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it\n this.recordSourceMappingEnd(funcDecl);\n\n this.emitParensAndCommentsInPlace(funcDecl, false);\n\n if (!isMember &&\n //funcDecl.name != null &&\n !hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression) &&\n (hasFlag(funcDecl.fncFlags, FncFlags.Definition) || funcDecl.isConstructor)) {\n this.writeLineToOutput(\"\");\n } else if (hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression)) {\n if (hasFlag(funcDecl.flags, ASTFlags.ExplicitSemicolon) || hasFlag(funcDecl.flags, ASTFlags.AutomaticSemicolon)) {\n // If either of these two flags are set, then the function expression is a statement. Terminate it.\n this.writeLineToOutput(\";\");\n }\n }\n /// TODO: See the other part of this at the beginning of function\n //if (funcDecl.preComments!=null && funcDecl.preComments.length>0) {\n // this.decreaseIndent();\n //} \n }\n\n public emitJavascriptModule(moduleDecl: ModuleDeclaration) {\n var modName = moduleDecl.name.actualText;\n if (isTSFile(modName)) {\n moduleDecl.name.setText(modName.substring(0, modName.length - 3));\n }\n else if (isSTRFile(modName)) {\n moduleDecl.name.setText(modName.substring(0, modName.length - 4));\n }\n\n if (!hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient)) {\n var isDynamicMod = hasFlag(moduleDecl.modFlags, ModuleFlags.IsDynamic);\n var prevOutFile = this.outfile;\n var prevOutFileName = this.emittingFileName;\n var prevAllSourceMappers = this.allSourceMappers;\n var prevSourceMapper = this.sourceMapper;\n var prevColumn = this.emitState.column;\n var prevLine = this.emitState.line;\n var temp = this.setContainer(EmitContainer.Module);\n var svModuleName = this.moduleName;\n var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);\n this.moduleDeclList[this.moduleDeclList.length] = moduleDecl;\n var isWholeFile = hasFlag(moduleDecl.modFlags, ModuleFlags.IsWholeFile);\n this.moduleName = moduleDecl.name.actualText;\n\n // prologue\n if (isDynamicMod) {\n // create the new outfile for this module\n var tsModFileName = stripQuotes(moduleDecl.name.actualText);\n var modFilePath = trimModName(tsModFileName) + \".js\";\n modFilePath = this.emitOptions.mapOutputFileName(modFilePath, TypeScriptCompiler.mapToJSFileName);\n\n if (this.emitOptions.ioHost) {\n // Ensure that the slashes are normalized so that the comparison is fair\n // REVIEW: Note that modFilePath is normalized to forward slashes in Parser.parse, so the \n // first call to switchToForwardSlashes is technically a no-op, but it will prevent us from\n // regressing if the parser changes\n if (switchToForwardSlashes(modFilePath) != switchToForwardSlashes(this.emittingFileName)) {\n this.emittingFileName = modFilePath;\n var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);\n this.outfile = this.createFile(this.emittingFileName, useUTF8InOutputfile);\n if (prevSourceMapper != null) {\n this.allSourceMappers = [];\n var sourceMappingFile = this.createFile(this.emittingFileName + SourceMapper.MapFileExtension, false);\n this.setSourceMappings(new TypeScript.SourceMapper(tsModFileName, this.emittingFileName, this.outfile, sourceMappingFile, this.errorReporter));\n this.emitState.column = 0;\n this.emitState.line = 0;\n }\n } else {\n CompilerDiagnostics.assert(this.emitOptions.outputMany, \"Cannot have dynamic modules compiling into single file\");\n }\n }\n\n this.setContainer(EmitContainer.DynamicModule); // discard the previous 'Module' container\n\n this.recordSourceMappingStart(moduleDecl);\n if (moduleGenTarget == ModuleGenTarget.Asynchronous) { // AMD\n var dependencyList = \"[\\\"require\\\", \\\"exports\\\"\";\n var importList = \"require, exports\";\n var importStatement: ImportDeclaration = null;\n\n // all dependencies are quoted\n for (var i = 0; i < (<ModuleType>moduleDecl.mod).importedModules.length; i++) {\n importStatement = (<ModuleType>moduleDecl.mod).importedModules[i]\n\n // if the imported module is only used in a type position, do not add it as a requirement\n if (importStatement.id.sym &&\n !(<TypeSymbol>importStatement.id.sym).onlyReferencedAsTypeRef) {\n if (i <= (<ModuleType>moduleDecl.mod).importedModules.length - 1) {\n dependencyList += \", \";\n importList += \", \";\n }\n\n importList += \"__\" + importStatement.id.actualText + \"__\";\n dependencyList += importStatement.firstAliasedModToString();\n }\n }\n\n // emit any potential amd dependencies\n for (var i = 0; i < moduleDecl.amdDependencies.length; i++) {\n dependencyList += \", \\\"\" + moduleDecl.amdDependencies[i] + \"\\\"\";\n }\n\n dependencyList += \"]\";\n\n this.writeLineToOutput(\"define(\" + dependencyList + \",\" + \" function(\" + importList + \") {\");\n }\n else { // Node\n\n }\n }\n else {\n\n if (!isExported) {\n this.recordSourceMappingStart(moduleDecl);\n this.writeToOutput(\"var \");\n this.recordSourceMappingStart(moduleDecl.name);\n this.writeToOutput(this.moduleName);\n this.recordSourceMappingEnd(moduleDecl.name);\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(moduleDecl);\n this.emitIndent();\n }\n\n this.writeToOutput(\"(\");\n this.recordSourceMappingStart(moduleDecl);\n this.writeToOutput(\"function (\");\n this.recordSourceMappingStart(moduleDecl.name);\n this.writeToOutput(this.moduleName);\n this.recordSourceMappingEnd(moduleDecl.name);\n this.writeLineToOutput(\") {\");\n }\n\n if (!isWholeFile) {\n this.recordSourceMappingNameStart(this.moduleName);\n }\n\n // body - don't indent for Node\n if (!isDynamicMod || moduleGenTarget == ModuleGenTarget.Asynchronous) {\n this.indenter.increaseIndent();\n }\n\n if (moduleDecl.modFlags & ModuleFlags.MustCaptureThis) {\n this.writeCaptureThisStatement(moduleDecl);\n }\n\n this.emitJavascriptList(moduleDecl.members, null, TokenID.Semicolon, true, false, false);\n if (!isDynamicMod || moduleGenTarget == ModuleGenTarget.Asynchronous) {\n this.indenter.decreaseIndent();\n }\n this.emitIndent();\n\n // epilogue\n if (isDynamicMod) {\n if (moduleGenTarget == ModuleGenTarget.Asynchronous) { // AMD\n this.writeLineToOutput(\"})\");\n }\n else { // Node\n }\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl);\n\n // close the module outfile, and restore the old one\n if (this.outfile != prevOutFile) {\n this.Close();\n if (prevSourceMapper != null) {\n this.allSourceMappers = prevAllSourceMappers;\n this.sourceMapper = prevSourceMapper;\n this.emitState.column = prevColumn;\n this.emitState.line = prevLine;\n }\n this.outfile = prevOutFile;\n this.emittingFileName = prevOutFileName;\n }\n }\n else {\n var containingMod: ModuleDeclaration = null;\n if (moduleDecl.type && moduleDecl.type.symbol.container && moduleDecl.type.symbol.container.declAST) {\n containingMod = <ModuleDeclaration>moduleDecl.type.symbol.container.declAST;\n }\n var parentIsDynamic = containingMod && hasFlag(containingMod.modFlags, ModuleFlags.IsDynamic);\n\n this.recordSourceMappingStart(moduleDecl.endingToken);\n if (temp == EmitContainer.Prog && isExported) {\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")(this.\" + this.moduleName + \" || (this.\" + this.moduleName + \" = {}));\");\n }\n else if (isExported || temp == EmitContainer.Prog) {\n var dotMod = svModuleName != \"\" ? (parentIsDynamic ? \"exports\" : svModuleName) + \".\" : svModuleName;\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")(\" + dotMod + this.moduleName + \" || (\" + dotMod + this.moduleName + \" = {}));\");\n }\n else if (!isExported && temp != EmitContainer.Prog) {\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")(\" + this.moduleName + \" || (\" + this.moduleName + \" = {}));\");\n }\n else {\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")();\");\n }\n this.recordSourceMappingEnd(moduleDecl);\n this.writeLineToOutput(\"\");\n if (temp != EmitContainer.Prog && isExported) {\n this.emitIndent();\n this.recordSourceMappingStart(moduleDecl);\n if (parentIsDynamic) {\n this.writeLineToOutput(\"var \" + this.moduleName + \" = exports.\" + this.moduleName + \";\");\n } else {\n this.writeLineToOutput(\"var \" + this.moduleName + \" = \" + svModuleName + \".\" + this.moduleName + \";\");\n }\n this.recordSourceMappingEnd(moduleDecl);\n }\n }\n\n this.setContainer(temp);\n this.moduleName = svModuleName;\n this.moduleDeclList.length--;\n }\n }\n\n public emitIndex(operand1: AST, operand2: AST) {\n var temp = this.setInObjectLiteral(false);\n this.emitJavascript(operand1, TokenID.Tilde, false);\n this.writeToOutput(\"[\");\n this.emitJavascriptList(operand2, \", \", TokenID.Comma, false, false, false);\n this.writeToOutput(\"]\");\n this.setInObjectLiteral(temp);\n }\n\n public emitStringLiteral(text: string) {\n // should preserve escape etc.\n // TODO: simplify object literal simple name\n this.writeToOutput(text);\n }\n\n public emitJavascriptFunction(funcDecl: FuncDecl) {\n if (hasFlag(funcDecl.fncFlags, FncFlags.Signature) || funcDecl.isOverload) {\n return;\n }\n var temp: number;\n var tempFnc = this.thisFnc;\n this.thisFnc = funcDecl;\n\n if (funcDecl.isConstructor) {\n temp = this.setContainer(EmitContainer.Constructor);\n }\n else {\n temp = this.setContainer(EmitContainer.Function);\n }\n\n var bases: ASTList = null;\n var hasSelfRef = false;\n var funcName = funcDecl.getNameText();\n\n if ((this.emitState.inObjectLiteral || !funcDecl.isAccessor()) &&\n ((temp != EmitContainer.Constructor) ||\n ((funcDecl.fncFlags & FncFlags.Method) == FncFlags.None))) {\n var tempLit = this.setInObjectLiteral(false);\n if (this.thisClassNode) {\n bases = this.thisClassNode.extendsList;\n }\n hasSelfRef = Emitter.shouldCaptureThis(funcDecl);\n this.recordSourceMappingStart(funcDecl);\n if (hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported) && funcDecl.type.symbol.container == this.checker.gloMod && !funcDecl.isConstructor) {\n this.writeToOutput(\"this.\" + funcName + \" = \");\n this.emitInnerFunction(funcDecl, false, false, bases, hasSelfRef, this.thisClassNode);\n }\n else {\n this.emitInnerFunction(funcDecl, (funcDecl.name && !funcDecl.name.isMissing()), false, bases, hasSelfRef, this.thisClassNode);\n }\n this.setInObjectLiteral(tempLit);\n }\n this.setContainer(temp);\n this.thisFnc = tempFnc;\n\n if (hasFlag(funcDecl.fncFlags, FncFlags.Definition)) {\n if (hasFlag(funcDecl.fncFlags, FncFlags.Static)) {\n if (this.thisClassNode) {\n if (funcDecl.isAccessor()) {\n this.emitPropertyAccessor(funcDecl, this.thisClassNode.name.actualText, false);\n }\n else {\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl);\n this.writeLineToOutput(this.thisClassNode.name.actualText + \".\" + funcName +\n \" = \" + funcName + \";\");\n this.recordSourceMappingEnd(funcDecl);\n }\n }\n }\n else if ((this.emitState.container == EmitContainer.Module || this.emitState.container == EmitContainer.DynamicModule) && hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported)) {\n this.emitIndent();\n var modName = this.emitState.container == EmitContainer.Module ? this.moduleName : \"exports\";\n this.recordSourceMappingStart(funcDecl);\n this.writeLineToOutput(modName + \".\" + funcName +\n \" = \" + funcName + \";\");\n this.recordSourceMappingEnd(funcDecl);\n }\n }\n }\n\n public emitAmbientVarDecl(varDecl: VarDecl) {\n if (varDecl.init) {\n this.emitParensAndCommentsInPlace(varDecl, true);\n this.recordSourceMappingStart(varDecl);\n this.recordSourceMappingStart(varDecl.id);\n this.writeToOutput(varDecl.id.actualText);\n this.recordSourceMappingEnd(varDecl.id);\n this.writeToOutput(\" = \");\n this.emitJavascript(varDecl.init, TokenID.Comma, false);\n this.recordSourceMappingEnd(varDecl);\n this.writeToOutput(\";\");\n this.emitParensAndCommentsInPlace(varDecl, false);\n }\n }\n\n private varListCount(): number {\n return this.varListCountStack[this.varListCountStack.length - 1];\n }\n\n // Emits \"var \" if it is allowed\n private emitVarDeclVar() {\n // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var\n // If it is var list of form var a = varList count will be 0\n if (this.varListCount() >= 0) {\n this.writeToOutput(\"var \");\n this.setInVarBlock(-this.varListCount());\n }\n return true;\n }\n\n private onEmitVar() {\n if (this.varListCount() > 0) {\n this.setInVarBlock(this.varListCount() - 1);\n }\n else if (this.varListCount() < 0) {\n this.setInVarBlock(this.varListCount() + 1);\n }\n }\n\n public emitJavascriptVarDecl(varDecl: VarDecl, tokenId: TokenID) {\n if ((varDecl.varFlags & VarFlags.Ambient) == VarFlags.Ambient) {\n this.emitAmbientVarDecl(varDecl);\n this.onEmitVar();\n }\n else {\n var sym = varDecl.sym;\n var hasInitializer = (varDecl.init != null);\n this.emitParensAndCommentsInPlace(varDecl, true);\n this.recordSourceMappingStart(varDecl);\n if (sym && sym.isMember() && sym.container &&\n (sym.container.kind() == SymbolKind.Type)) {\n var type = (<TypeSymbol>sym.container).type;\n if (type.isClass() && (!hasFlag(sym.flags, SymbolFlags.ModuleMember))) {\n // class\n if (this.emitState.container != EmitContainer.Args) {\n if (hasFlag(sym.flags, SymbolFlags.Static)) {\n this.writeToOutput(sym.container.name + \".\");\n }\n else {\n this.writeToOutput(\"this.\");\n }\n }\n }\n else if (type.hasImplementation()) {\n // module\n if (!hasFlag(sym.flags, SymbolFlags.Exported) && (sym.container == this.checker.gloMod || !hasFlag(sym.flags, SymbolFlags.Property))) {\n this.emitVarDeclVar();\n }\n else if (hasFlag(varDecl.varFlags, VarFlags.LocalStatic)) {\n this.writeToOutput(\".\");\n }\n else {\n if (this.emitState.container == EmitContainer.DynamicModule) {\n this.writeToOutput(\"exports.\");\n }\n else {\n this.writeToOutput(this.moduleName + \".\");\n }\n }\n }\n else {\n // function, constructor, method etc.\n if (tokenId != TokenID.OpenParen) {\n if (hasFlag(sym.flags, SymbolFlags.Exported) && sym.container == this.checker.gloMod) {\n this.writeToOutput(\"this.\");\n }\n else {\n this.emitVarDeclVar();\n }\n }\n }\n }\n else {\n if (tokenId != TokenID.OpenParen) {\n this.emitVarDeclVar();\n }\n }\n this.recordSourceMappingStart(varDecl.id);\n this.writeToOutput(varDecl.id.actualText);\n this.recordSourceMappingEnd(varDecl.id);\n if (hasInitializer) {\n this.writeToOutputTrimmable(\" = \");\n\n // Ensure we have a fresh var list count when recursing into the variable \n // initializer. We don't want our current list of variables to affect how we\n // emit nested variable lists.\n this.varListCountStack.push(0);\n this.emitJavascript(varDecl.init, TokenID.Comma, false);\n this.varListCountStack.pop();\n }\n this.onEmitVar();\n if ((tokenId != TokenID.OpenParen)) {\n if (this.varListCount() < 0) {\n this.writeToOutput(\", \");\n } else if (tokenId != TokenID.For) {\n this.writeToOutputTrimmable(\";\");\n }\n }\n this.recordSourceMappingEnd(varDecl);\n this.emitParensAndCommentsInPlace(varDecl, false);\n }\n }\n\n public declEnclosed(moduleDecl: ModuleDeclaration): bool {\n if (moduleDecl == null) {\n return true;\n }\n for (var i = 0, len = this.moduleDeclList.length; i < len; i++) {\n if (this.moduleDeclList[i] == moduleDecl) {\n return true;\n }\n }\n return false;\n }\n\n public emitJavascriptName(name: Identifier, addThis: bool) {\n var sym = name.sym;\n this.emitParensAndCommentsInPlace(name, true);\n this.recordSourceMappingStart(name);\n if (!name.isMissing()) {\n if (addThis && (this.emitState.container != EmitContainer.Args) && sym) {\n // TODO: flag global module with marker other than string name\n if (sym.container && (sym.container.name != globalId)) {\n if (hasFlag(sym.flags, SymbolFlags.Static) && (hasFlag(sym.flags, SymbolFlags.Property))) {\n if (sym.declModule && hasFlag(sym.declModule.modFlags, ModuleFlags.IsDynamic)) {\n this.writeToOutput(\"exports.\");\n }\n else {\n this.writeToOutput(sym.container.name + \".\");\n }\n }\n else if (sym.kind() == SymbolKind.Field) {\n var fieldSym = <FieldSymbol>sym;\n if (hasFlag(fieldSym.flags, SymbolFlags.ModuleMember)) {\n if ((sym.container != this.checker.gloMod) && ((hasFlag(sym.flags, SymbolFlags.Property)) || hasFlag(sym.flags, SymbolFlags.Exported))) {\n if (hasFlag(sym.declModule.modFlags, ModuleFlags.IsDynamic)) {\n this.writeToOutput(\"exports.\");\n }\n else {\n this.writeToOutput(sym.container.name + \".\");\n }\n }\n }\n else {\n if (sym.isInstanceProperty()) {\n this.emitThis();\n this.writeToOutput(\".\");\n }\n }\n }\n else if (sym.kind() == SymbolKind.Type) {\n if (sym.isInstanceProperty()) {\n var typeSym = <TypeSymbol>sym;\n var type = typeSym.type;\n if (type.call && !hasFlag(sym.flags, SymbolFlags.ModuleMember)) {\n this.emitThis();\n this.writeToOutput(\".\");\n }\n }\n else if ((sym.unitIndex != this.checker.locationInfo.unitIndex) || (!this.declEnclosed(sym.declModule))) {\n this.writeToOutput(sym.container.name + \".\")\n }\n }\n }\n else if (sym.container == this.checker.gloMod &&\n hasFlag(sym.flags, SymbolFlags.Exported) &&\n !hasFlag(sym.flags, SymbolFlags.Ambient) &&\n // check that it's a not a member of an ambient module...\n !((sym.isType() || sym.isMember()) &&\n sym.declModule &&\n hasFlag(sym.declModule.modFlags, ModuleFlags.Ambient)) &&\n this.emitState.container == EmitContainer.Prog &&\n sym.declAST.nodeType != NodeType.FuncDecl) {\n this.writeToOutput(\"this.\");\n }\n }\n\n // If it's a dynamic module, we need to print the \"require\" invocation\n if (sym &&\n sym.declAST &&\n sym.declAST.nodeType == NodeType.ModuleDeclaration &&\n (hasFlag((<ModuleDeclaration>sym.declAST).modFlags, ModuleFlags.IsDynamic))) {\n var moduleDecl: ModuleDeclaration = <ModuleDeclaration>sym.declAST;\n\n if (moduleGenTarget == ModuleGenTarget.Asynchronous) {\n this.writeLineToOutput(\"__\" + this.modAliasId + \"__;\");\n }\n else {\n var modPath = name.actualText;//(<ModuleDecl>moduleDecl.mod.symbol.declAST).name.actualText;\n var isAmbient = moduleDecl.mod.symbol.declAST && hasFlag((<ModuleDeclaration>moduleDecl.mod.symbol.declAST).modFlags, ModuleFlags.Ambient);\n modPath = isAmbient ? modPath : this.firstModAlias ? this.firstModAlias : quoteBaseName(modPath);\n modPath = isAmbient ? modPath : (!isRelative(stripQuotes(modPath)) ? quoteStr(\"./\" + stripQuotes(modPath)) : modPath);\n this.writeToOutput(\"require(\" + modPath + \")\");\n }\n }\n else {\n this.writeToOutput(name.actualText);\n }\n }\n this.recordSourceMappingEnd(name);\n this.emitParensAndCommentsInPlace(name, false);\n }\n\n public emitJavascriptStatements(stmts: AST, emitEmptyBod: bool) {\n if (stmts) {\n if (stmts.nodeType != NodeType.Block) {\n var hasContents = (stmts && (stmts.nodeType != NodeType.List || ((<ASTList>stmts).members.length > 0)));\n if (emitEmptyBod || hasContents) {\n var hasOnlyBlockStatement = ((stmts.nodeType == NodeType.Block) ||\n ((stmts.nodeType == NodeType.List) && ((<ASTList>stmts).members.length == 1) && ((<ASTList>stmts).members[0].nodeType == NodeType.Block)));\n\n this.recordSourceMappingStart(stmts);\n if (!hasOnlyBlockStatement) {\n this.writeLineToOutput(\" {\");\n this.indenter.increaseIndent();\n }\n this.emitJavascriptList(stmts, null, TokenID.Semicolon, true, false, false);\n if (!hasOnlyBlockStatement) {\n this.writeLineToOutput(\"\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeToOutput(\"}\");\n }\n this.recordSourceMappingEnd(stmts);\n }\n }\n else {\n this.emitJavascript(stmts, TokenID.Semicolon, true);\n }\n }\n else if (emitEmptyBod) {\n this.writeToOutput(\"{ }\");\n }\n }\n\n public emitBareJavascriptStatements(stmts: AST, emitClassPropertiesAfterSuperCall: bool = false) {\n // just the statements without enclosing curly braces\n if (stmts.nodeType != NodeType.Block) {\n if (stmts.nodeType == NodeType.List) {\n var stmtList = <ASTList>stmts;\n if ((stmtList.members.length == 2) &&\n (stmtList.members[0].nodeType == NodeType.Block) &&\n (stmtList.members[1].nodeType == NodeType.EndCode)) {\n this.emitJavascript(stmtList.members[0], TokenID.Semicolon, true);\n this.writeLineToOutput(\"\");\n }\n else {\n this.emitJavascriptList(stmts, null, TokenID.Semicolon, true, false, emitClassPropertiesAfterSuperCall);\n }\n }\n else {\n this.emitJavascript(stmts, TokenID.Semicolon, true);\n }\n }\n else {\n this.emitJavascript(stmts, TokenID.Semicolon, true);\n }\n }\n\n public recordSourceMappingNameStart(name: string) {\n if (this.sourceMapper) {\n var finalName = name;\n if (!name) {\n finalName = \"\";\n } else if (this.sourceMapper.currentNameIndex.length > 0) {\n finalName = this.sourceMapper.names[this.sourceMapper.currentNameIndex.length - 1] + \".\" + name;\n }\n\n // We are currently not looking for duplicate but that is possible.\n this.sourceMapper.names.push(finalName);\n this.sourceMapper.currentNameIndex.push(this.sourceMapper.names.length - 1);\n }\n }\n\n public recordSourceMappingNameEnd() {\n if (this.sourceMapper) {\n this.sourceMapper.currentNameIndex.pop();\n }\n }\n\n public recordSourceMappingStart(ast: ASTSpan) {\n if (this.sourceMapper && isValidAstNode(ast)) {\n var lineCol = { line: -1, col: -1 };\n var sourceMapping = new SourceMapping();\n sourceMapping.start.emittedColumn = this.emitState.column;\n sourceMapping.start.emittedLine = this.emitState.line;\n // REVIEW: check time consumed by this binary search (about two per leaf statement)\n getSourceLineColFromMap(lineCol, ast.minChar, this.checker.locationInfo.lineMap);\n sourceMapping.start.sourceColumn = lineCol.col;\n sourceMapping.start.sourceLine = lineCol.line;\n getSourceLineColFromMap(lineCol, ast.limChar, this.checker.locationInfo.lineMap);\n sourceMapping.end.sourceColumn = lineCol.col;\n sourceMapping.end.sourceLine = lineCol.line;\n if (this.sourceMapper.currentNameIndex.length > 0) {\n sourceMapping.nameIndex = this.sourceMapper.currentNameIndex[this.sourceMapper.currentNameIndex.length - 1];\n }\n // Set parent and child relationship\n var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];\n siblings.push(sourceMapping);\n this.sourceMapper.currentMappings.push(sourceMapping.childMappings);\n }\n }\n\n public recordSourceMappingEnd(ast: ASTSpan) {\n if (this.sourceMapper && isValidAstNode(ast)) {\n // Pop source mapping childs\n this.sourceMapper.currentMappings.pop();\n\n // Get the last source mapping from sibling list = which is the one we are recording end for\n var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];\n var sourceMapping = siblings[siblings.length - 1];\n\n sourceMapping.end.emittedColumn = this.emitState.column;\n sourceMapping.end.emittedLine = this.emitState.line;\n }\n }\n\n public Close() {\n if (this.sourceMapper != null) {\n SourceMapper.EmitSourceMapping(this.allSourceMappers);\n }\n try {\n // Closing files could result in exceptions, report them if they occur\n this.outfile.Close();\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n\n public emitJavascriptList(ast: AST, delimiter: string, tokenId: TokenID, startLine: bool, onlyStatics: bool, emitClassPropertiesAfterSuperCall: bool = false, emitPrologue? = false, requiresExtendsBlock?: bool) {\n if (ast == null) {\n return;\n }\n else if (ast.nodeType != NodeType.List) {\n this.emitPrologue(emitPrologue);\n this.emitJavascript(ast, tokenId, startLine);\n }\n else {\n var list = <ASTList>ast;\n if (list.members.length == 0) {\n return;\n }\n\n this.emitParensAndCommentsInPlace(ast, true);\n var len = list.members.length;\n for (var i = 0; i < len; i++) {\n if (emitPrologue) {\n // If the list has Strict mode flags, emit prologue after first statement\n // otherwise emit before first statement\n if (i == 1 || !hasFlag(list.flags, ASTFlags.StrictMode)) {\n this.emitPrologue(requiresExtendsBlock);\n emitPrologue = false;\n }\n }\n\n // In some circumstances, class property initializers must be emitted immediately after the 'super' constructor\n // call which, in these cases, must be the first statement in the constructor body\n if (i == 1 && emitClassPropertiesAfterSuperCall) {\n\n // emit any parameter properties first\n var constructorDecl = (<ClassDeclaration>this.thisClassNode).constructorDecl;\n\n if (constructorDecl && constructorDecl.arguments) {\n var argsLen = constructorDecl.arguments.members.length;\n for (var iArg = 0; iArg < argsLen; iArg++) {\n var arg = <BoundDecl>constructorDecl.arguments.members[iArg];\n if ((arg.varFlags & VarFlags.Property) != VarFlags.None) {\n this.emitIndent();\n this.recordSourceMappingStart(arg);\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(\"this.\" + arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeToOutput(\" = \");\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(arg);\n }\n }\n }\n\n var nProps = (<ASTList>this.thisClassNode.members).members.length;\n\n for (var iMember = 0; iMember < nProps; iMember++) {\n if ((<ASTList>this.thisClassNode.members).members[iMember].nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>(<ASTList>this.thisClassNode.members).members[iMember];\n if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n this.emitIndent();\n this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n this.writeLineToOutput(\"\");\n }\n }\n }\n }\n\n var emitNode = list.members[i];\n\n var isStaticDecl =\n (emitNode.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>emitNode).fncFlags, FncFlags.Static)) ||\n (emitNode.nodeType == NodeType.VarDecl && hasFlag((<VarDecl>emitNode).varFlags, VarFlags.Static))\n\n if (onlyStatics ? !isStaticDecl : isStaticDecl) {\n continue;\n }\n this.emitJavascript(emitNode, tokenId, startLine);\n\n if (delimiter && (i < (len - 1))) {\n if (startLine) {\n this.writeLineToOutput(delimiter);\n }\n else {\n this.writeToOutput(delimiter);\n }\n }\n else if (startLine &&\n (emitNode.nodeType != NodeType.ModuleDeclaration) &&\n (emitNode.nodeType != NodeType.InterfaceDeclaration) &&\n (!((emitNode.nodeType == NodeType.VarDecl) &&\n ((((<VarDecl>emitNode).varFlags) & VarFlags.Ambient) == VarFlags.Ambient) &&\n (((<VarDecl>emitNode).init) == null)) && this.varListCount() >= 0) &&\n (emitNode.nodeType != NodeType.Block || (<Block>emitNode).isStatementBlock) &&\n (emitNode.nodeType != NodeType.EndCode) &&\n (emitNode.nodeType != NodeType.FuncDecl)) {\n this.writeLineToOutput(\"\");\n }\n }\n this.emitParensAndCommentsInPlace(ast, false);\n }\n }\n\n // tokenId is the id the preceding token\n public emitJavascript(ast: AST, tokenId: TokenID, startLine: bool) {\n if (ast == null) {\n return;\n }\n\n // REVIEW: simplify rules for indenting\n if (startLine && (this.indenter.indentAmt > 0) && (ast.nodeType != NodeType.List) &&\n (ast.nodeType != NodeType.Block)) {\n if ((ast.nodeType != NodeType.InterfaceDeclaration) &&\n (!((ast.nodeType == NodeType.VarDecl) &&\n ((((<VarDecl>ast).varFlags) & VarFlags.Ambient) == VarFlags.Ambient) &&\n (((<VarDecl>ast).init) == null)) && this.varListCount() >= 0) &&\n (ast.nodeType != NodeType.EndCode) &&\n ((ast.nodeType != NodeType.FuncDecl) ||\n (this.emitState.container != EmitContainer.Constructor))) {\n this.emitIndent();\n }\n }\n\n ast.emit(this, tokenId, startLine);\n\n if ((tokenId == TokenID.Semicolon) && (ast.nodeType < NodeType.GeneralNode)) {\n this.writeToOutput(\";\");\n }\n }\n\n public emitPropertyAccessor(funcDecl: FuncDecl, className: string, isProto: bool) {\n if (!(<FieldSymbol>funcDecl.accessorSymbol).hasBeenEmitted) {\n var accessorSymbol = <FieldSymbol>funcDecl.accessorSymbol;\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl);\n this.writeLineToOutput(\"Object.defineProperty(\" + className + (isProto ? \".prototype, \\\"\" : \", \\\"\") + funcDecl.name.actualText + \"\\\"\" + \", {\");\n this.indenter.increaseIndent();\n\n if (accessorSymbol.getter) {\n var getter: FuncDecl = <FuncDecl>accessorSymbol.getter.declAST;\n\n this.emitIndent();\n this.recordSourceMappingStart(getter);\n this.writeToOutput(\"get: \");\n this.emitInnerFunction(getter, false, isProto, null, Emitter.shouldCaptureThis(getter), null);\n this.writeLineToOutput(\",\");\n }\n\n if (accessorSymbol.setter) {\n var setter: FuncDecl = <FuncDecl>accessorSymbol.setter.declAST;\n\n this.emitIndent();\n this.recordSourceMappingStart(setter);\n this.writeToOutput(\"set: \");\n this.emitInnerFunction(setter, false, isProto, null, Emitter.shouldCaptureThis(setter), null);\n this.writeLineToOutput(\",\");\n }\n\n this.emitIndent();\n this.writeLineToOutput(\"enumerable: true,\");\n this.emitIndent();\n this.writeLineToOutput(\"configurable: true\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeLineToOutput(\"});\");\n this.recordSourceMappingEnd(funcDecl);\n\n accessorSymbol.hasBeenEmitted = true;\n }\n }\n\n public emitPrototypeMember(member: AST, className: string) {\n if (member.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>member;\n if (funcDecl.isAccessor()) {\n this.emitPropertyAccessor(funcDecl, className, true);\n }\n else {\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl);\n this.writeToOutput(className + \".prototype.\" + funcDecl.getNameText() + \" = \");\n this.emitInnerFunction(funcDecl, false, true, null, Emitter.shouldCaptureThis(funcDecl), null);\n this.writeLineToOutput(\";\");\n }\n }\n else if (member.nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>member;\n\n if (varDecl.init) {\n this.emitIndent();\n this.recordSourceMappingStart(varDecl);\n this.recordSourceMappingStart(varDecl.id);\n this.writeToOutput(className + \".prototype.\" + varDecl.id.actualText);\n this.recordSourceMappingEnd(varDecl.id);\n this.writeToOutput(\" = \");\n this.emitJavascript(varDecl.init, TokenID.Equals, false);\n this.recordSourceMappingEnd(varDecl);\n this.writeLineToOutput(\";\");\n }\n }\n }\n\n public emitAddBaseMethods(className: string, base: Type, classDecl: TypeDeclaration): void {\n if (base.members) {\n var baseSymbol = base.symbol;\n var baseName = baseSymbol.name;\n if (baseSymbol.declModule != classDecl.type.symbol.declModule) {\n baseName = baseSymbol.fullName();\n }\n base.members.allMembers.map(function(key, s, c) {\n var sym = <Symbol>s;\n if ((sym.kind() == SymbolKind.Type) && (<TypeSymbol>sym).type.call) {\n this.recordSourceMappingStart(sym.declAST);\n this.writeLineToOutput(className + \".prototype.\" + sym.name + \" = \" +\n baseName + \".prototype.\" + sym.name + \";\");\n this.recordSourceMappingEnd(sym.declAST);\n }\n }, null);\n }\n if (base.extendsList) {\n for (var i = 0, len = base.extendsList.length; i < len; i++) {\n this.emitAddBaseMethods(className, base.extendsList[i], classDecl);\n }\n }\n }\n\n public emitJavascriptClass(classDecl: ClassDeclaration) {\n if (!hasFlag(classDecl.varFlags, VarFlags.Ambient)) {\n var svClassNode = this.thisClassNode;\n var i = 0;\n this.thisClassNode = classDecl;\n var className = classDecl.name.actualText;\n this.emitParensAndCommentsInPlace(classDecl, true);\n var temp = this.setContainer(EmitContainer.Class);\n\n this.recordSourceMappingStart(classDecl);\n if (hasFlag(classDecl.varFlags, VarFlags.Exported) && classDecl.type.symbol.container == this.checker.gloMod) {\n this.writeToOutput(\"this.\" + className);\n }\n else {\n this.writeToOutput(\"var \" + className);\n }\n\n //if (hasFlag(classDecl.varFlags, VarFlags.Exported) && (temp == EmitContainer.Module || temp == EmitContainer.DynamicModule)) {\n // var modName = temp == EmitContainer.Module ? this.moduleName : \"exports\";\n // this.writeToOutput(\" = \" + modName + \".\" + className);\n //}\n\n var hasBaseClass = classDecl.extendsList && classDecl.extendsList.members.length;\n var baseNameDecl: AST = null;\n var baseName: AST = null;\n\n if (hasBaseClass) {\n this.writeLineToOutput(\" = (function (_super) {\");\n } else {\n this.writeLineToOutput(\" = (function () {\");\n }\n\n this.recordSourceMappingNameStart(className);\n this.indenter.increaseIndent();\n\n if (hasBaseClass) {\n baseNameDecl = classDecl.extendsList.members[0];\n baseName = baseNameDecl.nodeType == NodeType.Call ? (<CallExpression>baseNameDecl).target : baseNameDecl;\n this.emitIndent();\n this.writeLineToOutput(\"__extends(\" + className + \", _super);\");\n }\n\n this.emitIndent();\n\n var constrDecl = classDecl.constructorDecl;\n\n // output constructor\n if (constrDecl) {\n // declared constructor\n this.emitJavascript(classDecl.constructorDecl, TokenID.OpenParen, false);\n\n }\n else {\n var wroteProps = 0;\n\n this.recordSourceMappingStart(classDecl);\n // default constructor\n this.indenter.increaseIndent();\n this.writeToOutput(\"function \" + classDecl.name.actualText + \"() {\");\n this.recordSourceMappingNameStart(\"constructor\");\n if (hasBaseClass) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n this.writeLineToOutput(\"_super.apply(this, arguments);\");\n wroteProps++;\n }\n\n if (classDecl.varFlags & VarFlags.MustCaptureThis) {\n this.writeCaptureThisStatement(classDecl);\n }\n\n var members = (<ASTList>this.thisClassNode.members).members\n\n // output initialized properties\n for (var i = 0; i < members.length; i++) {\n if (members[i].nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>members[i];\n if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n wroteProps++;\n }\n }\n }\n if (wroteProps) {\n this.writeLineToOutput(\"\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeLineToOutput(\"}\");\n }\n else {\n this.writeLineToOutput(\" }\");\n this.indenter.decreaseIndent();\n }\n this.recordSourceMappingNameEnd();\n this.recordSourceMappingEnd(classDecl);\n }\n\n var membersLen = classDecl.members.members.length;\n for (var j = 0; j < membersLen; j++) {\n\n var memberDecl: AST = classDecl.members.members[j];\n\n if (memberDecl.nodeType == NodeType.FuncDecl) {\n var fn = <FuncDecl>memberDecl;\n\n if (hasFlag(fn.fncFlags, FncFlags.Method) && !fn.isSignature()) {\n if (!hasFlag(fn.fncFlags, FncFlags.Static)) {\n this.emitPrototypeMember(fn, className);\n }\n else { // static functions\n if (fn.isAccessor()) {\n this.emitPropertyAccessor(fn, this.thisClassNode.name.actualText, false);\n }\n else {\n this.emitIndent();\n this.recordSourceMappingStart(fn)\n this.writeToOutput(classDecl.name.actualText + \".\" + fn.name.actualText + \" = \");\n this.emitInnerFunction(fn, (fn.name && !fn.name.isMissing()), true,\n null, Emitter.shouldCaptureThis(fn), null);\n this.writeLineToOutput(\";\");\n }\n }\n }\n }\n else if (memberDecl.nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>memberDecl;\n if (hasFlag(varDecl.varFlags, VarFlags.Static)) {\n\n if (varDecl.init) {\n // EMITREVIEW\n this.emitIndent();\n this.recordSourceMappingStart(varDecl);\n this.writeToOutput(classDecl.name.actualText + \".\" + varDecl.id.actualText + \" = \");\n this.emitJavascript(varDecl.init, TokenID.Equals, false);\n // EMITREVIEW\n\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(varDecl);\n }\n }\n }\n else {\n throw Error(\"We want to catch this\");\n }\n }\n\n this.emitIndent();\n this.recordSourceMappingStart(classDecl.endingToken);\n this.writeLineToOutput(\"return \" + className + \";\");\n this.recordSourceMappingEnd(classDecl.endingToken);\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.recordSourceMappingStart(classDecl.endingToken);\n this.writeToOutput(\"}\");\n this.recordSourceMappingNameEnd();\n this.recordSourceMappingEnd(classDecl.endingToken);\n this.recordSourceMappingStart(classDecl);\n this.writeToOutput(\")(\");\n if (hasBaseClass)\n this.emitJavascript(baseName, TokenID.Tilde, false);\n this.writeToOutput(\");\");\n this.recordSourceMappingEnd(classDecl);\n\n if ((temp == EmitContainer.Module || temp == EmitContainer.DynamicModule) && hasFlag(classDecl.varFlags, VarFlags.Exported)) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n var modName = temp == EmitContainer.Module ? this.moduleName : \"exports\";\n this.recordSourceMappingStart(classDecl);\n this.writeToOutput(modName + \".\" + className + \" = \" + className + \";\");\n this.recordSourceMappingEnd(classDecl);\n }\n\n this.emitIndent();\n this.recordSourceMappingEnd(classDecl);\n this.emitParensAndCommentsInPlace(classDecl, false);\n this.setContainer(temp);\n this.thisClassNode = svClassNode;\n }\n }\n\n public emitPrologue(reqInherits: bool) {\n if (!this.prologueEmitted) {\n if (reqInherits) {\n this.prologueEmitted = true;\n this.writeLineToOutput(\"var __extends = this.__extends || function (d, b) {\");\n this.writeLineToOutput(\" function __() { this.constructor = d; }\");\n this.writeLineToOutput(\" __.prototype = b.prototype;\");\n this.writeLineToOutput(\" d.prototype = new __();\");\n this.writeLineToOutput(\"};\");\n }\n if (this.checker.mustCaptureGlobalThis) {\n this.prologueEmitted = true;\n this.writeLineToOutput(this.captureThisStmtString);\n }\n }\n }\n\n public emitSuperReference() {\n this.writeToOutput(\"_super.prototype\");\n }\n\n public emitSuperCall(callEx: CallExpression): bool {\n if (callEx.target.nodeType == NodeType.Dot) {\n var dotNode = <BinaryExpression>callEx.target;\n if (dotNode.operand1.nodeType == NodeType.Super) {\n this.emitJavascript(dotNode, TokenID.OpenParen, false);\n this.writeToOutput(\".call(\");\n this.emitThis();\n if (callEx.arguments && callEx.arguments.members.length > 0) {\n this.writeToOutput(\", \");\n this.emitJavascriptList(callEx.arguments, \", \", TokenID.Comma, false, false, false);\n }\n this.writeToOutput(\")\");\n return true;\n }\n }\n return false;\n }\n\n public emitThis() {\n if (this.thisFnc && !this.thisFnc.isMethod() && (!this.thisFnc.isConstructor)) {\n this.writeToOutput(\"_this\");\n }\n else {\n this.writeToOutput(\"this\");\n }\n }\n\n private static shouldCaptureThis(func: FuncDecl): bool {\n // Super calls use 'this' reference. If super call is in a lambda, 'this' value needs to be captured in the parent.\n return func.hasSelfReference() || func.hasSuperReferenceInFatArrowFunction();\n }\n\n private createFile(fileName: string, useUTF8: bool): ITextWriter {\n try {\n return this.emitOptions.ioHost.createFile(fileName, useUTF8);\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export interface ILineCol {\n line: number;\n col: number;\n }\n\n export class ErrorReporter {\n public parser: Parser = null;\n public checker: TypeChecker = null;\n public lineCol = { line: 0, col: 0 };\n public emitAsComments = true;\n public hasErrors = false;\n public pushToErrorSink = false;\n public errorSink: string[] = [];\n\n constructor (public outfile: ITextWriter) { }\n\n public getCapturedErrors() { return this.errorSink; }\n public freeCapturedErrors() { this.errorSink = []; }\n public captureError(emsg: string) { this.errorSink[this.errorSink.length] = emsg; }\n\n public setErrOut(outerr) {\n this.outfile = outerr;\n this.emitAsComments = false;\n }\n\n public emitPrefix() {\n if (this.emitAsComments) {\n this.outfile.Write(\"// \");\n }\n this.outfile.Write(this.checker.locationInfo.filename + \"(\" + this.lineCol.line + \",\" + this.lineCol.col + \"): \");\n }\n\n public writePrefix(ast: AST): void {\n if (ast) {\n this.setError(ast);\n }\n else {\n this.lineCol.line = 0;\n this.lineCol.col = 0;\n }\n this.emitPrefix();\n }\n\n public writePrefixFromSym(symbol: Symbol): void {\n if (symbol && this.checker.locationInfo.lineMap) {\n getSourceLineColFromMap(this.lineCol, symbol.location,\n this.checker.locationInfo.lineMap);\n }\n else {\n this.lineCol.line = -1;\n this.lineCol.col = -1;\n }\n this.emitPrefix();\n }\n\n public setError(ast: AST) {\n if (ast) {\n ast.flags |= ASTFlags.Error;\n if (this.checker.locationInfo.lineMap) {\n getSourceLineColFromMap(this.lineCol, ast.minChar, this.checker.locationInfo.lineMap);\n }\n }\n }\n\n public reportError(ast: AST, message: string) {\n if (this.pushToErrorSink) {\n this.captureError(message);\n return;\n }\n\n this.hasErrors = true;\n if (ast && this.parser.errorRecovery && this.parser.errorCallback) {\n var len = (ast.limChar - ast.minChar);\n this.parser.errorCallback(ast.minChar, len, message, this.checker.locationInfo.unitIndex);\n }\n else {\n this.writePrefix(ast);\n this.outfile.WriteLine(message); // Right after the semi-colon\n }\n }\n\n public reportErrorFromSym(symbol: Symbol, message: string) {\n if (this.pushToErrorSink) {\n this.captureError(message);\n return;\n }\n\n this.hasErrors = true;\n if (this.parser.errorRecovery && this.parser.errorCallback) {\n this.parser.errorCallback(symbol.location, symbol.length, message, this.checker.locationInfo.unitIndex);\n }\n else {\n this.writePrefixFromSym(symbol);\n this.outfile.WriteLine(message);\n }\n }\n\n public emitterError(ast: AST, message: string) {\n this.reportError(ast, message);\n // Emitter errors are not recoverable, stop immediately\n throw Error(\"EmitError\");\n }\n\n public duplicateIdentifier(ast: AST, name: string) {\n this.reportError(ast, \"Duplicate identifier '\" + name + \"'\");\n }\n\n public showRef(ast: AST, text: string, symbol: Symbol) {\n var defLineCol = { line: -1, col: -1 };\n // TODO: multiple def locations\n this.parser.getSourceLineCol(defLineCol, symbol.location);\n this.reportError(ast, \"symbol \" + text + \" defined at (\" + defLineCol.line + \",\" +\n defLineCol.col + \")\");\n }\n\n public unresolvedSymbol(ast: AST, name: string) {\n this.reportError(ast, \"The name '\" + name + \"' does not exist in the current scope\");\n }\n\n public symbolDoesNotReferToAValue(ast: AST, name: string): void {\n this.reportError(ast, \"The name '\" + name + \"' does not refer to a value\");\n }\n\n public styleError(ast: AST, msg: string): void {\n var bkThrow = this.pushToErrorSink;\n this.pushToErrorSink = false;\n this.reportError(ast, \"STYLE: \" + msg);\n this.pushToErrorSink = bkThrow;\n }\n\n public simpleError(ast: AST, msg: string): void {\n this.reportError(ast, msg);\n }\n\n public simpleErrorFromSym(sym: Symbol, msg: string): void {\n this.reportErrorFromSym(sym, msg);\n }\n\n public invalidSuperReference(ast: AST) {\n this.simpleError(ast, \"Keyword 'super' can only be used inside a class instance method\");\n }\n\n public valueCannotBeModified(ast: AST) {\n this.simpleError(ast, \"The left-hand side of an assignment expression must be a variable, property or indexer\");\n }\n\n public invalidCall(ast: CallExpression, nodeType: number, scope: SymbolScope): void {\n var targetType = ast.target.type;\n var typeName = targetType.getScopedTypeName(scope);\n if (targetType.construct && (nodeType == NodeType.Call)) {\n this.reportError(ast, \"Value of type '\" + typeName + \"' is not callable. Did you mean to include 'new'?\");\n } else {\n var catString = (nodeType == NodeType.Call) ? \"callable\" : \"newable\";\n\n this.reportError(ast, \"Value of type '\" + typeName + \"' is not \" + catString);\n }\n }\n\n public indexLHS(ast: BinaryExpression, scope: SymbolScope): void {\n var targetType = ast.operand1.type.getScopedTypeName(scope);\n var indexType = ast.operand2.type.getScopedTypeName(scope);\n this.simpleError(ast, \"Value of type '\" + targetType + \"' is not indexable by type '\" + indexType + \"'\");\n }\n\n public incompatibleTypes(ast: AST, t1: Type, t2: Type, op: string, scope: SymbolScope, comparisonInfo?:TypeComparisonInfo) {\n if (!t1) {\n t1 = this.checker.anyType;\n }\n if (!t2) {\n t2 = this.checker.anyType;\n }\n\n var reason = comparisonInfo ? comparisonInfo.message : \"\";\n if (op) {\n this.reportError(ast, \"Operator '\" + op + \"' cannot be applied to types '\" + t1.getScopedTypeName(scope) +\n \"' and '\" + t2.getScopedTypeName(scope) + \"'\" + (reason ? \": \" + reason : \"\"));\n }\n else {\n this.reportError(ast, \"Cannot convert '\" + t1.getScopedTypeName(scope) +\n \"' to '\" + t2.getScopedTypeName(scope) + \"'\" + (reason ? \": \" + reason : \"\"));\n }\n }\n\n public expectedClassOrInterface(ast: AST): void {\n this.simpleError(ast, \"Expected var, class, interface, or module\");\n }\n\n public unaryOperatorTypeError(ast: AST, op: string, type: Type) {\n this.reportError(ast, \"Operator '\" + op + \"' cannot be applied to type '\" + type.getTypeName() + \"'\");\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export function hasFlag(val: number, flag: number) {\n return (val & flag) != 0;\n }\n\n export enum ErrorRecoverySet {\n None = 0,\n Comma = 1, // Comma\n SColon = 1 << 1, // SColon\n Asg = 1 << 2, // Asg\n BinOp = 1 << 3, // Lsh, Rsh, Rs2, Le, Ge, INSTANCEOF, EQ, NE, Eqv, NEqv, LogAnd, LogOr, AsgMul, AsgDiv\n // AsgMod, AsgAdd, AsgSub, AsgLsh, AsgRsh, AsgRs2, AsgAnd, AsgXor, AsgOr, QMark, Mult, Div, \n // Pct, GT, LT, And, Xor, Or\n RBrack = 1 << 4, // RBrack\n RCurly = 1 << 5, // RCurly\n RParen = 1 << 6, // RParen\n Dot = 1 << 7, // Dot\n Colon = 1 << 8, // Colon\n PrimType = 1 << 9, // number, string, bool\n AddOp = 1 << 10, // Add, Sub\n LCurly = 1 << 11, // LCurly\n PreOp = 1 << 12, // Tilde, Bang, Inc, Dec\n RegExp = 1 << 13, // RegExp\n LParen = 1 << 14, // LParen\n LBrack = 1 << 15, // LBrack\n Scope = 1 << 16, // Scope\n In = 1 << 17, // IN\n SCase = 1 << 18, // CASE, DEFAULT\n Else = 1 << 19, // ELSE\n Catch = 1 << 20, // CATCH, FINALLY\n Var = 1 << 21, // \n Stmt = 1 << 22, // BREAK, RETURN, THROW, DEBUGGER, FOR, SWITCH, DO, IF, TRY, WITH\n While = 1 << 23, // WHILE\n ID = 1 << 24, // ID\n Prefix = 1 << 25, // VOID, DELETE, TYPEOF, AWAIT\n Literal = 1 << 26, // IntCon, FltCon, StrCon\n RLit = 1 << 27, // THIS, TRUE, FALSE, NULL\n Func = 1 << 28, // FUNCTION\n EOF = 1 << 29, // EOF\n\n // REVIEW: Name this something clearer.\n TypeScriptS = 1 << 30, // PROPERTY, PRIVATE, STATIC, INTERFACE, CLASS, MODULE, EXPORT, IMPORT\n ExprStart = SColon | AddOp | LCurly | PreOp | RegExp | LParen | LBrack | ID | Prefix | RLit | Func | Literal,\n StmtStart = ExprStart | SColon | Var | Stmt | While | TypeScriptS,\n Postfix = Dot | LParen | LBrack,\n }\n\n export enum AllowedElements {\n None = 0,\n ModuleDeclarations = 1 << 2,\n ClassDeclarations = 1 << 3,\n InterfaceDeclarations = 1 << 4,\n AmbientDeclarations = 1 << 10,\n Properties = 1 << 11,\n\n Global = ModuleDeclarations | ClassDeclarations | InterfaceDeclarations | AmbientDeclarations,\n QuickParse = Global | Properties,\n }\n\n export enum Modifiers {\n None = 0,\n Private = 1,\n Public = 1 << 1,\n Readonly = 1 << 2,\n Ambient = 1 << 3,\n Exported = 1 << 4,\n Getter = 1 << 5,\n Setter = 1 << 6,\n Static = 1 << 7,\n }\n\n export enum ASTFlags {\n None = 0,\n ExplicitSemicolon = 1, // statment terminated by an explicit semicolon\n AutomaticSemicolon = 1 << 1, // statment terminated by an automatic semicolon\n Writeable = 1 << 2, // node is lhs that can be modified\n Error = 1 << 3, // node has an error\n DotLHSPartial = 1 << 4, // node is the lhs of an incomplete dot expr at cursor\n DotLHS = 1 << 5, // node is the lhs of a dot expr\n IsStatement = 1 << 6, // node is a statement\n StrictMode = 1 << 7, // node is in the strict mode environment\n PossibleOptionalParameter = 1 << 8,\n ClassBaseConstructorCall = 1 << 9,\n OptionalName = 1 << 10,\n // REVIEW: This flag is to mark lambda nodes to note that the LParen of an expression has already been matched in the lambda header.\n // The flag is used to communicate this piece of information to the calling parseTerm, which intern will remove it.\n // Once we have a better way to associate information with nodes, this flag should not be used.\n SkipNextRParen = 1 << 11, \n }\n\n export enum DeclFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n }\n\n export enum ModuleFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n IsEnum = 1 << 8,\n ShouldEmitModuleDecl = 1 << 9,\n IsWholeFile = 1 << 10,\n IsDynamic = 1 << 11,\n MustCaptureThis = 1 << 12,\n }\n\n export enum SymbolFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n Property = 1 << 8,\n Readonly = 1 << 9,\n ModuleMember = 1 << 10,\n InterfaceMember = 1 << 11,\n ClassMember = 1 << 12,\n BuiltIn = 1 << 13,\n TypeSetDuringScopeAssignment = 1 << 14,\n Constant = 1 << 15,\n Optional = 1 << 16,\n RecursivelyReferenced = 1 << 17,\n Bound = 1 << 18,\n CompilerGenerated = 1 << 19,\n }\n\n export enum VarFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n AutoInit = 1 << 8,\n Property = 1 << 9,\n Readonly = 1 << 10,\n Class = 1 << 11,\n ClassProperty = 1 << 12,\n ClassBodyProperty = 1 << 13,\n ClassConstructorProperty = 1 << 14,\n ClassSuperMustBeFirstCallInConstructor = 1 << 15,\n Constant = 1 << 16,\n MustCaptureThis = 1 << 17,\n }\n\n export enum FncFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n Definition = 1 << 8,\n Signature = 1 << 9,\n Method = 1 << 10,\n HasReturnExpression = 1 << 11,\n CallMember = 1 << 12,\n ConstructMember = 1 << 13,\n HasSelfReference = 1 << 14,\n IsFatArrowFunction = 1 << 15,\n IndexerMember = 1 << 16,\n IsFunctionExpression = 1 << 17,\n ClassMethod = 1 << 18,\n ClassPropertyMethodExported = 1 << 19,\n HasSuperReferenceInFatArrowFunction = 1 << 20,\n IsPropertyBound = 1 << 21,\n }\n\n export enum SignatureFlags {\n None = 0,\n IsIndexer = 1,\n IsStringIndexer = 1 << 1,\n IsNumberIndexer = 1 << 2,\n }\n\n export function ToDeclFlags(fncFlags: FncFlags) : DeclFlags;\n export function ToDeclFlags(varFlags: VarFlags) : DeclFlags;\n export function ToDeclFlags(symFlags: SymbolFlags): DeclFlags;\n export function ToDeclFlags(moduleFlags: ModuleFlags): DeclFlags;\n export function ToDeclFlags(fncOrVarOrSymbolOrModuleFlags: any) {\n return <DeclFlags>fncOrVarOrSymbolOrModuleFlags;\n }\n\n export enum TypeFlags {\n None = 0,\n HasImplementation = 1,\n HasSelfReference = 1 << 1,\n MergeResult = 1 << 2,\n IsEnum = 1 << 3,\n BuildingName = 1 << 4,\n HasBaseType = 1 << 5,\n HasBaseTypeOfObject = 1 << 6,\n IsClass = 1 << 7,\n }\n\n export enum TypeRelationshipFlags {\n SuccessfulComparison = 0,\n SourceIsNullTargetIsVoidOrUndefined = 1,\n RequiredPropertyIsMissing = 1 << 1,\n IncompatibleSignatures = 1 << 2,\n SourceSignatureHasTooManyParameters = 3,\n IncompatibleReturnTypes = 1 << 4,\n IncompatiblePropertyTypes = 1 << 5,\n IncompatibleParameterTypes = 1 << 6,\n }\n\n export enum CodeGenTarget {\n ES3 = 0,\n ES5 = 1,\n }\n\n export enum ModuleGenTarget {\n Synchronous = 0,\n Asynchronous = 1,\n Local = 1 << 1,\n }\n\n // Compiler defaults to generating ES5-compliant code for\n // - getters and setters\n export var codeGenTarget: CodeGenTarget = CodeGenTarget.ES3;\n\n export var moduleGenTarget: ModuleGenTarget = ModuleGenTarget.Synchronous;\n\n export var optimizeModuleCodeGen = true;\n\n export function flagsToString(e, flags: number): string {\n var builder = \"\";\n for (var i = 1; i < (1 << 31) ; i = i << 1) {\n if ((flags & i) != 0) {\n for (var k in e) {\n if (e[k] == i) {\n if (builder.length > 0) {\n builder += \"|\";\n }\n builder += k;\n break;\n }\n }\n }\n }\n return builder;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export class BlockIntrinsics {\n public prototype = undefined;\n public toString = undefined;\n public toLocaleString = undefined;\n public valueOf = undefined;\n public hasOwnProperty = undefined;\n public propertyIsEnumerable = undefined;\n public isPrototypeOf = undefined;\n\n constructor () {\n // initialize the 'constructor' field\n this[\"constructor\"] = undefined;\n }\n }\n\n export interface IHashTable {\n getAllKeys(): string[];\n add(key: string, data): bool;\n addOrUpdate(key: string, data): bool;\n map(fn: (k: string, v, c) => void , context): void;\n every(fn: (k: string, v, c) => bool, context): bool;\n some(fn: (k: string, v, c) => bool, context): bool;\n count(): number;\n lookup(key: string): any;\n }\n\n export class StringHashTable implements IHashTable {\n public itemCount = 0;\n public table = <any>(<any> new BlockIntrinsics());\n\n public getAllKeys(): string[]{\n var result: string[] = [];\n for (var k in this.table) {\n if (this.table[k] != undefined) {\n result[result.length] = k;\n }\n }\n return result;\n }\n\n public add(key: string, data): bool {\n if (this.table[key] != undefined) {\n return false;\n }\n this.table[key] = data;\n this.itemCount++;\n return true;\n }\n\n public addOrUpdate(key: string, data): bool {\n if (this.table[key] != undefined) {\n this.table[key] = data;\n return false;\n }\n this.table[key] = data;\n this.itemCount++;\n return true;\n }\n\n public map(fn: (k: string, v, c) => void , context) {\n for (var k in this.table) {\n var data = this.table[k];\n if (data != undefined) {\n fn(k, this.table[k], context);\n }\n }\n }\n\n public every(fn: (k: string, v, c) => bool, context) {\n for (var k in this.table) {\n var data = this.table[k];\n if (data != undefined) {\n if (!fn(k, this.table[k], context)) {\n return false;\n }\n }\n }\n return true;\n }\n\n public some(fn: (k: string, v, c) => bool, context) {\n for (var k in this.table) {\n var data = this.table[k];\n if (data != undefined) {\n if (fn(k, this.table[k], context)) {\n return true;\n }\n }\n }\n return false;\n }\n\n public count(): number { return this.itemCount; }\n\n public lookup(key: string) {\n var data = this.table[key];\n if (data != undefined) {\n return data;\n }\n else {\n return (null);\n }\n }\n }\n\n // The resident table is expected to reference the same table object, whereas the \n // transientTable may reference different objects over time\n // REVIEW: WARNING: For performance reasons, neither the primary nor secondary table may be null\n export class DualStringHashTable implements IHashTable {\n\n public insertPrimary = true;\n\n constructor (public primaryTable: IHashTable,\n public secondaryTable: IHashTable) { }\n\n public getAllKeys(): string[]{\n return this.primaryTable.getAllKeys().concat(this.secondaryTable.getAllKeys());\n }\n\n public add(key: string, data): bool {\n if (this.insertPrimary) {\n return this.primaryTable.add(key, data);\n }\n else {\n return this.secondaryTable.add(key, data);\n }\n }\n\n public addOrUpdate(key: string, data): bool {\n if (this.insertPrimary) {\n return this.primaryTable.addOrUpdate(key, data);\n }\n else {\n return this.secondaryTable.addOrUpdate(key, data);\n }\n }\n\n public map(fn: (k: string, v, c) => void , context) {\n this.primaryTable.map(fn, context);\n this.secondaryTable.map(fn, context);\n }\n\n public every(fn: (k: string, v, c) => bool, context) {\n return this.primaryTable.every(fn, context) && this.secondaryTable.every(fn, context);\n }\n\n public some(fn: (k: string, v, c) => bool, context) {\n return this.primaryTable.some(fn, context) || this.secondaryTable.some(fn, context);\n }\n\n public count() {\n return this.primaryTable.count() + this.secondaryTable.count();\n }\n\n public lookup(key: string) {\n var data = this.primaryTable.lookup(key);\n if (data != undefined) {\n return data;\n }\n else {\n return this.secondaryTable.lookup(key);\n }\n }\n }\n\n export function numberHashFn(key: number): number {\n var c2 = 0x27d4eb2d; // a prime or an odd constant\n key = (key ^ 61) ^ (key >>> 16);\n key = key + (key << 3);\n key = key ^ (key >>> 4);\n key = key * c2;\n key = key ^ (key >>> 15);\n return key;\n }\n\n export function combineHashes(key1: number, key2: number) {\n return key2 ^ ((key1 >> 5) + key1);\n }\n\n export class HashEntry {\n public next: HashEntry;\n\n constructor (public key, public data) { }\n }\n\n export class HashTable {\n public itemCount: number = 0;\n public table = new HashEntry[];\n\n constructor (public size: number, public hashFn: (key) =>number,\n public equalsFn: (key1, key2) =>bool) {\n for (var i: number = 0; i < this.size; i++) {\n this.table[i] = null;\n }\n }\n\n public add(key, data): bool {\n var current: HashEntry;\n var entry: HashEntry = new HashEntry(key, data);\n var val: number = this.hashFn(key);\n val = val % this.size;\n\n for (current = this.table[val]; current != null ; current = current.next) {\n if (this.equalsFn(key, current.key)) {\n return false;\n }\n }\n entry.next = this.table[val];\n this.table[val] = entry;\n this.itemCount++;\n return true;\n }\n\n public remove(key) {\n var current: HashEntry;\n var val: number = this.hashFn(key);\n val = val % this.size;\n var result = null;\n var prevEntry: HashEntry = null;\n\n for (current = this.table[val]; current != null ; current = current.next) {\n if (this.equalsFn(key, current.key)) {\n result = current.data;\n this.itemCount--;\n if (prevEntry) {\n prevEntry.next = current.next;\n }\n else {\n this.table[val] = current.next;\n }\n break;\n }\n prevEntry = current;\n }\n return result;\n }\n\n public count(): number { return this.itemCount; }\n\n public lookup(key) {\n var current: HashEntry;\n var val: number = this.hashFn(key);\n val = val % this.size;\n for (current = this.table[val]; current != null ; current = current.next) {\n if (this.equalsFn(key, current.key)) {\n return (current.data);\n }\n }\n return (null);\n }\n }\n\n // Simple Hash table with list of keys and values matching each other at the given index\n export class SimpleHashTable {\n private keys = [];\n private values = [];\n\n public lookup(key, findValue?: bool) {\n var searchArray = this.keys;\n if (findValue) {\n searchArray = this.values;\n }\n\n for (var i = 0; i < searchArray.length; i++) {\n if (searchArray[i] == key) {\n return {\n key: this.keys[i],\n data: this.values[i],\n };\n }\n }\n return null;\n }\n\n public add(key, data): bool {\n var lookupData = this.lookup(key);\n if (lookupData) {\n return false;\n }\n\n this.keys[this.keys.length] = key;\n this.values[this.values.length] = data;\n\n return true;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export class IncrementalParser {\n \n private astLogger: AstLogger;\n\n constructor (private logger: TypeScript.ILogger) {\n this.astLogger = new AstLogger(this.logger);\n }\n\n //\n // Return \"null\" if \"editRange\" cannot be safely determined to be inside a single scope.\n //\n public getEnclosingScopeContextIfSingleScopeEdit(previousScript: Script, scriptId: string, newSourceText: ISourceText, editRange: ScriptEditRange): EnclosingScopeContext {\n this.logger.log(\"checkEditsInsideSingleScope(\\\"\" + scriptId + \"\\\")\");\n\n if (editRange === null) {\n throw new Error(\"editRange should be valid\");\n }\n\n if (editRange.isUnknown()) {\n this.logger.log(\" Bailing out because edit range is unknown\");\n return null;\n }\n\n var scope1 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.minChar, false/*isMemberCompletion*/);\n var scope2 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.limChar, false/*isMemberCompletion*/);\n if (scope1 == null || scope2 == null) {\n this.logger.log(\" Bailing out because containing scopes cannot be determined\");\n return null;\n }\n\n // We only support changes within a single containing scope\n if (scope1.scopeStartAST !== scope2.scopeStartAST) {\n this.logger.log(\" Bailing out because edit overlaps 2 disctint scopes\");\n return null;\n }\n\n var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;\n if (newScopeLength <= 0) {\n this.logger.log(\" Bailing out because scope has been entirely removed from new source text\");\n return null;\n }\n\n return scope1;\n }\n\n public attemptIncrementalUpdateUnit(previousScript: Script, scriptId: string, newSourceText: ISourceText, editRange: ScriptEditRange): UpdateUnitResult {\n this.logger.log(\"attemptIncrementalUpdateUnit(\\\"\" + scriptId + \"\\\")\");\n\n if (editRange === null) {\n throw new Error(\"editRange should be valid\");\n }\n\n var scope1 = this.getEnclosingScopeContextIfSingleScopeEdit(previousScript, scriptId, newSourceText, editRange);\n if (scope1 === null) {\n return null;\n }\n\n var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;\n\n // Heuristic: if the range to reparse is too big, bail out. \n // This is because a full parse will be faster than an incremental parse followed by all the necessary fix-ups \n if (newScopeLength >= newSourceText.getLength() / 2) {\n this.logger.log(\" Bailing out because range of scope to reparse (\" + newScopeLength + \" characters) is greater than half the size of the source text\");\n return null;\n }\n\n // Capture parsing errors so that they are part of \"updateResult\"\n var parseErrors: TypeScript.ErrorEntry[] = [];\n var errorCapture = function(minChar: number, charLen: number, message: string, unitIndex: number): void {\n parseErrors.push(new TypeScript.ErrorEntry(unitIndex, minChar, minChar + charLen, message));\n };\n\n var quickParseResult = TypeScript.quickParse(this.logger, scope1.scopeStartAST, newSourceText, scope1.scopeStartAST.minChar, scope1.scopeStartAST.minChar + newScopeLength, errorCapture);\n if (quickParseResult.endLexState != TypeScript.LexState.Start) {\n this.logger.log(\" Bailing out because scope contains unterminated comment\");\n return null;\n }\n\n var scriptFragment = quickParseResult.Script;\n if (scriptFragment.vars.members.length !== 0) {\n this.logger.log(\" Bailing out because new source text defines variables\");\n return null;\n }\n\n //if (scriptFragment.scopes.members.length !== 1) {\n // logger.log(\" Bailing out because new source text defines more than one scope (or none)\");\n // return null;\n //}\n\n // This detects adding close curlies, since they have the side effect of having the parser \n // parse more members in the scope range.\n if (scriptFragment.bod.members.length !== 1) {\n this.logger.log(\" Bailing out because new source text defines more than one scope (or none)\");\n return null;\n }\n\n var oldScope = scope1.scopeStartAST;\n var newScope = scriptFragment.bod.members[0];\n\n if (oldScope.nodeType != newScope.nodeType) {\n this.logger.log(\" Bailing out because new source text does not define the same scope type as the existing scope\");\n return null;\n }\n\n if (!(<any>oldScope).leftCurlyCount || !(<any>oldScope).rightCurlyCount) {\n this.logger.log(\" Bailing out because sopce doesn't have left/right curly count\");\n return null;\n }\n\n if ((<any>oldScope).leftCurlyCount !== (<any>newScope).leftCurlyCount) {\n this.logger.log(\" Bailing out because new source text contains more (or fewer) left curly braces\");\n return null;\n }\n\n if ((<any>oldScope).rightCurlyCount !== (<any>newScope).rightCurlyCount) {\n this.logger.log(\" Bailing out because new source text contains more (or fewer) right curly braces\");\n return null;\n }\n\n if (newScope.minChar !== 0) {\n this.logger.log(\" Bailing out because new function declaration does not start at position 0\");\n return null;\n }\n\n if (newScope.limChar !== newScopeLength) {\n this.logger.log(\" Bailing out because new function declaration does not end at the new end position\");\n return null;\n }\n\n return TypeScript.UpdateUnitResult.singleScopeEdits(previousScript, scriptFragment, oldScope, newScope, editRange, parseErrors);\n }\n\n public mergeTrees(updateResult: UpdateUnitResult): void {\n TypeScript.timeFunction(this.logger, \"mergeTrees()\", () => {\n var editRange = new ScriptEditRange(updateResult.scope1.minChar, updateResult.scope1.limChar, updateResult.editRange.delta);\n // Update positions in current ast\n this.applyDeltaPosition(updateResult.script1, editRange.limChar, editRange.delta);\n // Update positions in new (partial) ast\n this.applyDeltaPosition(updateResult.script2, 0, editRange.minChar);\n // Merge linemaps\n this.mergeLocationInfo(updateResult.script1, updateResult.script2, editRange);\n // Replace old AST for scope with new one\n this.replaceAST(updateResult.script1, updateResult.scope1, updateResult.scope2);\n });\n }\n\n private replaceAST(script: TypeScript.AST, oldAst: TypeScript.AST, newAst: TypeScript.AST) {\n var pre = (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) => {\n if (cur === oldAst) {\n // Transfer comments ownership to new AST. We need this because when \"quick parsing\" the\n // new AST, we don't take into account the text before and after the \"minChar/limChar\" pair\n // of the scope, which don't include pre/post-comments.\n newAst.preComments = cur.preComments;\n newAst.postComments = cur.postComments;\n\n this.logger.log(\"replaced old AST node with new one in script AST\");\n walker.options.stopWalk();\n return newAst;\n }\n\n // Avoid visiting sub-trees outside of the edit range\n if (TypeScript.isValidAstNode(cur)) {\n if (cur.limChar < oldAst.minChar || cur.minChar > oldAst.limChar) {\n walker.options.goChildren = false;\n }\n }\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(script, pre);\n }\n\n private mergeLocationInfo(script: TypeScript.Script, partial: TypeScript.Script, editRange: ScriptEditRange) {\n // Don't merger these fields, as the original script has the right values\n //script.locationInfo.unitIndex = partial.locationInfo.unitIndex;\n //script.locationInfo.filename = partial.locationInfo.filename;\n\n var lineMap1 = script.locationInfo.lineMap;\n var lineMap2 = partial.locationInfo.lineMap;\n\n if (this.logger.information()) {\n this.logger.log(\"lineMap1 (before):\");\n this.astLogger.logLinemap(lineMap1);\n this.logger.log(\"lineMap2 (quick parse):\");\n this.astLogger.logLinemap(lineMap2);\n this.logger.log(\"EditRange=\" + editRange);\n }\n\n // Skip entries < minChar\n var i1 = 2; // lineMap[0] is always undefined, lineMap[1] is always 0.\n var i2 = 2; // lineMap[0] is always undefined, lineMap[1] is always 0.\n var len1 = lineMap1.length;\n var len2 = lineMap2.length;\n while (i1 < len1) {\n if (lineMap1[i1] <= editRange.minChar) {\n // Nothing to do for this entry, since it's before the range of the change\n i1++;\n } else if (lineMap1[i1] >= editRange.limChar) {\n // Apply delta to this entry, since it's outside the range of the change\n lineMap1[i1] += editRange.delta;\n i1++;\n }\n else {\n if (i2 < len2) {\n // Add a new entry to lineMap1 corresponding to lineMap2 in new range\n lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);\n i1++;\n len1++;\n i2++;\n }\n else { /* i2 >= len 2 */\n // Remove this entry, since there is no corresponding entry in the new map\n lineMap1.splice(i1, 1);\n len1--;\n }\n }\n }\n // Merge the remaining entries in lineMap2 while maintaing the constraint that a lineMap is sorted\n if (i2 < len2) {\n // i1 >= len1 && i2 < len2 \n if (lineMap1[len1 - 1] >= (lineMap2[i2] + editRange.minChar)) {\n // lineMap2 needs to be merged within lineMap1\n i1 = 2;\n while (i1 < len1 && i2 < len2) {\n if (lineMap1[i1] < (lineMap2[i2] + editRange.minChar)) {\n i1++;\n }\n else {\n lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);\n i1++;\n len1++;\n i2++;\n }\n }\n }\n\n // Append all the remaining entries in lineMap2 to the end of lineMap1\n for (; i2 < len2; i2++) {\n lineMap1.push(lineMap2[i2] + editRange.minChar);\n }\n }\n\n if (this.logger.information()) {\n this.logger.log(\"lineMap1 (after merge):\");\n this.astLogger.logLinemap(lineMap1);\n }\n }\n\n private applyDeltaPosition(ast: TypeScript.AST, start: number, delta: number) {\n var applyDelta = (ast: TypeScript.AST) => {\n if (ast.minChar !== -1 && ast.minChar >= start) {\n ast.minChar += delta;\n }\n if (ast.limChar !== -1 && ast.limChar >= start) {\n ast.limChar += delta;\n }\n }\n\n var applyDeltaToComments = (comments: TypeScript.Comment[]) => {\n if (comments && comments.length > 0) {\n for (var i = 0; i < comments.length; i++) {\n applyDelta(comments[i]);\n }\n }\n }\n\n var pre = function(cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n // *Before* applying delta to this, check if we need to go to children\n if (cur.limChar !== -1 && cur.limChar < start) {\n walker.options.goChildren = false; // Done with applying Delta for this sub-tree\n }\n\n // Apply delta to this node\n applyDelta(cur);\n applyDeltaToComments(cur.preComments);\n applyDeltaToComments(cur.postComments);\n\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(ast, pre);\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\ninterface IResolvedFile {\n content: string;\n path: string;\n}\n\ninterface IFileWatcher {\n close(): void;\n}\n\ninterface IIO {\n readFile(path: string): string;\n writeFile(path: string, contents: string): void;\n createFile(path: string, useUTF8?: bool): ITextWriter;\n deleteFile(path: string): void;\n dir(path: string, re?: RegExp, options?: { recursive?: bool; }): string[];\n fileExists(path: string): bool;\n directoryExists(path: string): bool;\n createDirectory(path: string): void;\n resolvePath(path: string): string;\n dirName(path: string): string;\n findFile(rootPath: string, partialFilePath: string): IResolvedFile;\n print(str: string): void;\n printLine(str: string): void;\n arguments: string[];\n stderr: ITextWriter;\n stdout: ITextWriter;\n watchFile(filename: string, callback: (string) => void ): IFileWatcher;\n run(source: string, filename: string): void;\n getExecutingFilePath(): string;\n quit(exitCode?: number);\n}\n\nmodule IOUtils {\n // Creates the directory including its parent if not already present\n function createDirectoryStructure(ioHost: IIO, dirName: string) {\n if (ioHost.directoryExists(dirName)) {\n return;\n }\n\n var parentDirectory = ioHost.dirName(dirName);\n if (parentDirectory != \"\") {\n createDirectoryStructure(ioHost, parentDirectory);\n }\n ioHost.createDirectory(dirName);\n }\n\n // Creates a file including its directory structure if not already present\n export function createFileAndFolderStructure(ioHost: IIO, fileName: string, useUTF8?: bool) {\n var path = ioHost.resolvePath(fileName);\n var dirName = ioHost.dirName(path);\n createDirectoryStructure(ioHost, dirName);\n return ioHost.createFile(path, useUTF8);\n }\n\n export function throwIOError(message: string, error: Error) {\n var errorMessage = message;\n if (error && error.message) {\n errorMessage += (\" \" + error.message);\n }\n throw new Error(errorMessage);\n }\n}\n\n// Declare dependencies needed for all supported hosts\ndeclare class Enumerator {\n public atEnd(): bool;\n public moveNext();\n public item(): any;\n constructor (o: any);\n}\ndeclare function setTimeout(callback: () =>void , ms?: number);\ndeclare var require: any;\ndeclare module process {\n export var argv: string[];\n export var platform: string;\n export function on(event: string, handler: (any) => void ): void;\n export module stdout {\n export function write(str: string);\n }\n export module stderr {\n export function write(str: string);\n }\n export module mainModule {\n export var filename: string;\n }\n export function exit(exitCode?: number);\n}\n\nvar IO = (function() {\n\n // Create an IO object for use inside WindowsScriptHost hosts\n // Depends on WSCript and FileSystemObject\n function getWindowsScriptHostIO(): IIO {\n var fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n var streamObjectPool = [];\n\n function getStreamObject(): any { \n if (streamObjectPool.length > 0) {\n return streamObjectPool.pop();\n } else {\n return new ActiveXObject(\"ADODB.Stream\");\n }\n }\n\n function releaseStreamObject(obj: any) { \n streamObjectPool.push(obj);\n }\n\n var args = [];\n for (var i = 0; i < WScript.Arguments.length; i++) {\n args[i] = WScript.Arguments.Item(i);\n }\n\n return {\n readFile: function(path) {\n try {\n var streamObj = getStreamObject();\n streamObj.Open();\n streamObj.Type = 2; // Text data\n streamObj.Charset = 'x-ansi'; // Assume we are reading ansi text\n streamObj.LoadFromFile(path);\n var bomChar = streamObj.ReadText(2); // Read the BOM char\n streamObj.Position = 0; // Position has to be at 0 before changing the encoding\n if ((bomChar.charCodeAt(0) == 0xFE && bomChar.charCodeAt(1) == 0xFF)\n || (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) {\n streamObj.Charset = 'unicode';\n } else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) {\n streamObj.Charset = 'utf-8'; \n }\n\n // Read the whole file\n var str = streamObj.ReadText(-1 /* read from the current position to EOS */);\n streamObj.Close();\n releaseStreamObject(streamObj);\n return <string>str;\n }\n catch (err) {\n IOUtils.throwIOError(\"Error reading file \\\"\" + path + \"\\\".\", err);\n }\n },\n\n writeFile: function(path, contents) {\n var file = this.createFile(path);\n file.Write(contents);\n file.Close();\n },\n\n fileExists: function(path: string): bool {\n return fso.FileExists(path);\n },\n\n resolvePath: function(path: string): string {\n return fso.GetAbsolutePathName(path);\n },\n\n dirName: function(path: string): string {\n return fso.GetParentFolderName(path);\n },\n\n findFile: function(rootPath: string, partialFilePath: string): IResolvedFile {\n var path = fso.GetAbsolutePathName(rootPath) + \"/\" + partialFilePath;\n\n while (true) {\n if (fso.FileExists(path)) {\n try {\n var content = this.readFile(path);\n return { content: content, path: path };\n }\n catch (err) {\n //Tools.CompilerDiagnostics.debugPrint(\"Could not find \" + path + \", trying parent\");\n }\n }\n else {\n rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath));\n\n if (rootPath == \"\") {\n return null;\n }\n else {\n path = fso.BuildPath(rootPath, partialFilePath);\n }\n }\n }\n },\n\n deleteFile: function(path: string): void {\n try {\n if (fso.FileExists(path)) {\n fso.DeleteFile(path, true); // true: delete read-only files\n }\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't delete file '\" + path + \"'.\", e);\n }\n },\n\n createFile: function (path, useUTF8?) {\n try {\n var streamObj = getStreamObject();\n streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi';\n streamObj.Open();\n return {\n Write: function (str) { streamObj.WriteText(str, 0); },\n WriteLine: function (str) { streamObj.WriteText(str, 1); },\n Close: function() {\n try {\n streamObj.SaveToFile(path, 2);\n } catch (saveError) {\n IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", saveError);\n }\n finally {\n if (streamObj.State != 0 /*adStateClosed*/) {\n streamObj.Close();\n }\n releaseStreamObject(streamObj);\n }\n }\n };\n } catch (creationError) {\n IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", creationError);\n }\n },\n\n directoryExists: function(path) {\n return <bool>fso.FolderExists(path);\n },\n\n createDirectory: function(path) {\n try {\n if (!this.directoryExists(path)) {\n fso.CreateFolder(path);\n }\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't create directory '\" + path + \"'.\", e);\n }\n },\n\n dir: function(path, spec?, options?) {\n options = options || <{ recursive?: bool; }>{};\n function filesInFolder(folder, root): string[]{\n var paths = [];\n var fc: Enumerator;\n\n if (options.recursive) {\n fc = new Enumerator(folder.subfolders);\n\n for (; !fc.atEnd() ; fc.moveNext()) {\n paths = paths.concat(filesInFolder(fc.item(), root + \"/\" + fc.item().Name));\n }\n }\n\n fc = new Enumerator(folder.files);\n\n for (; !fc.atEnd() ; fc.moveNext()) {\n if (!spec || fc.item().Name.match(spec)) {\n paths.push(root + \"/\" + fc.item().Name);\n }\n }\n\n return paths;\n }\n\n var folder = fso.GetFolder(path);\n var paths = [];\n\n return filesInFolder(folder, path);\n },\n\n print: function(str) {\n WScript.StdOut.Write(str);\n },\n\n printLine: function(str) {\n WScript.Echo(str);\n },\n\n arguments: <string[]>args,\n stderr: WScript.StdErr,\n stdout: WScript.StdOut,\n watchFile: null,\n run: function(source, filename) {\n try {\n eval(source);\n } catch (e) {\n IOUtils.throwIOError(\"Error while executing file '\" + filename + \"'.\", e);\n }\n },\n getExecutingFilePath: function () {\n return WScript.ScriptFullName;\n },\n quit: function (exitCode? : number = 0) {\n try {\n WScript.Quit(exitCode);\n } catch (e) {\n }\n }\n }\n\n };\n\n // Create an IO object for use inside Node.js hosts\n // Depends on 'fs' and 'path' modules\n function getNodeIO(): IIO {\n\n var _fs = require('fs');\n var _path = require('path');\n var _module = require('module');\n\n return {\n readFile: function(file) {\n try {\n var buffer = _fs.readFileSync(file);\n switch (buffer[0]) {\n case 0xFE:\n if (buffer[1] == 0xFF) {\n // utf16-be. Reading the buffer as big endian is not supported, so convert it to \n // Little Endian first\n var i = 0;\n while ((i + 1) < buffer.length) {\n var temp = buffer[i]\n buffer[i] = buffer[i + 1];\n buffer[i + 1] = temp;\n i += 2;\n }\n return buffer.toString(\"ucs2\", 2);\n }\n break;\n case 0xFF:\n if (buffer[1] == 0xFE) {\n // utf16-le \n return buffer.toString(\"ucs2\", 2);\n }\n break;\n case 0xEF:\n if (buffer[1] == 0xBB) {\n // utf-8\n return buffer.toString(\"utf8\", 3);\n }\n }\n // Default behaviour\n return buffer.toString();\n } catch (e) {\n IOUtils.throwIOError(\"Error reading file \\\"\" + file + \"\\\".\", e);\n }\n },\n writeFile: <(path: string, contents: string) => void >_fs.writeFileSync,\n deleteFile: function(path) {\n try {\n _fs.unlinkSync(path);\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't delete file '\" + path + \"'.\", e);\n }\n },\n fileExists: function(path): bool {\n return _fs.existsSync(path);\n },\n createFile: function(path, useUTF8?) {\n function mkdirRecursiveSync(path) {\n var stats = _fs.statSync(path);\n if (stats.isFile()) {\n IOUtils.throwIOError(\"\\\"\" + path + \"\\\" exists but isn't a directory.\", null);\n } else if (stats.isDirectory()) {\n return;\n } else {\n mkdirRecursiveSync(_path.dirname(path));\n _fs.mkdirSync(path, 0775);\n }\n }\n\n mkdirRecursiveSync(_path.dirname(path));\n\n try {\n var fd = _fs.openSync(path, 'w');\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", e);\n }\n return {\n Write: function(str) { _fs.writeSync(fd, str); },\n WriteLine: function(str) { _fs.writeSync(fd, str + '\\r\\n'); },\n Close: function() { _fs.closeSync(fd); fd = null; }\n };\n },\n dir: function dir(path, spec?, options?) {\n options = options || <{ recursive?: bool; }>{};\n\n function filesInFolder(folder: string): string[]{\n var paths = [];\n\n var files = _fs.readdirSync(folder);\n for (var i = 0; i < files.length; i++) {\n var stat = _fs.statSync(folder + \"/\" + files[i]);\n if (options.recursive && stat.isDirectory()) {\n paths = paths.concat(filesInFolder(folder + \"/\" + files[i]));\n } else if (stat.isFile() && (!spec || files[i].match(spec))) {\n paths.push(folder + \"/\" + files[i]);\n }\n }\n\n return paths;\n }\n\n return filesInFolder(path);\n },\n createDirectory: function(path: string): void {\n try {\n if (!this.directoryExists(path)) {\n _fs.mkdirSync(path);\n }\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't create directory '\" + path + \"'.\", e);\n }\n },\n\n directoryExists: function(path: string): bool {\n return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory();\n },\n resolvePath: function(path: string): string {\n return _path.resolve(path);\n },\n dirName: function(path: string): string {\n return _path.dirname(path);\n },\n findFile: function(rootPath: string, partialFilePath): IResolvedFile {\n var path = rootPath + \"/\" + partialFilePath;\n\n while (true) {\n if (_fs.existsSync(path)) {\n try {\n var content = this.readFile(path);\n return { content: content, path: path };\n } catch (err) {\n //Tools.CompilerDiagnostics.debugPrint((\"Could not find \" + path) + \", trying parent\");\n }\n }\n else {\n var parentPath = _path.resolve(rootPath, \"..\");\n\n // Node will just continue to repeat the root path, rather than return null\n if (rootPath === parentPath) {\n return null;\n }\n else {\n rootPath = parentPath;\n path = _path.resolve(rootPath, partialFilePath);\n }\n }\n }\n },\n print: function(str) { process.stdout.write(str) },\n printLine: function(str) { process.stdout.write(str + '\\n') },\n arguments: process.argv.slice(2),\n stderr: {\n Write: function(str) { process.stderr.write(str); },\n WriteLine: function(str) { process.stderr.write(str + '\\n'); },\n Close: function() { }\n },\n stdout: {\n Write: function(str) { process.stdout.write(str); },\n WriteLine: function(str) { process.stdout.write(str + '\\n'); },\n Close: function() { }\n },\n watchFile: function(filename: string, callback: (string) => void ): IFileWatcher {\n var firstRun = true;\n var processingChange = false;\n\n var fileChanged: any = function(curr, prev) {\n if (!firstRun) {\n if (curr.mtime < prev.mtime) {\n return;\n }\n\n _fs.unwatchFile(filename, fileChanged);\n if (!processingChange) {\n processingChange = true;\n callback(filename);\n setTimeout(function() { processingChange = false; }, 100);\n }\n }\n firstRun = false;\n _fs.watchFile(filename, { persistent: true, interval: 500 }, fileChanged);\n };\n\n fileChanged();\n return {\n filename: filename,\n close: function() {\n _fs.unwatchFile(filename, fileChanged);\n }\n };\n },\n run: function(source, filename) {\n require.main.filename = filename;\n require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename)));\n require.main._compile(source, filename);\n }, \n getExecutingFilePath: function () {\n return process.mainModule.filename;\n },\n quit: process.exit\n }\n };\n\n if (typeof ActiveXObject === \"function\")\n return getWindowsScriptHostIO();\n else if (typeof require === \"function\")\n return getNodeIO();\n else\n return null; // Unsupported host\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n // Note: Any addition to the NodeType should also be supported with addition to AstWalkerDetailCallback\n export enum NodeType {\n None,\n Empty,\n EmptyExpr,\n True,\n False,\n This,\n Super,\n QString,\n Regex,\n Null,\n ArrayLit,\n ObjectLit,\n Void,\n Comma,\n Pos,\n Neg,\n Delete,\n Await,\n In,\n Dot,\n From,\n Is,\n InstOf,\n Typeof,\n NumberLit,\n Name,\n TypeRef,\n Index,\n Call,\n New,\n Asg,\n AsgAdd,\n AsgSub,\n AsgDiv,\n AsgMul,\n AsgMod,\n AsgAnd,\n AsgXor,\n AsgOr,\n AsgLsh,\n AsgRsh,\n AsgRs2,\n ConditionalExpression,\n LogOr,\n LogAnd,\n Or,\n Xor,\n And,\n Eq,\n Ne,\n Eqv,\n NEqv,\n Lt,\n Le,\n Gt,\n Ge,\n Add,\n Sub,\n Mul,\n Div,\n Mod,\n Lsh,\n Rsh,\n Rs2,\n Not,\n LogNot,\n IncPre,\n DecPre,\n IncPost,\n DecPost,\n TypeAssertion,\n FuncDecl,\n Member,\n VarDecl,\n ArgDecl,\n Return,\n Break,\n Continue,\n Throw,\n For,\n ForIn,\n If,\n While,\n DoWhile,\n Block,\n Case,\n Switch,\n Try,\n TryCatch,\n TryFinally,\n Finally,\n Catch,\n List,\n Script,\n ClassDeclaration,\n InterfaceDeclaration,\n ModuleDeclaration,\n ImportDeclaration,\n With,\n Label,\n LabeledStatement,\n EBStart,\n GotoEB,\n EndCode,\n Error,\n Comment,\n Debugger,\n GeneralNode = FuncDecl,\n LastAsg = AsgRs2,\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///<reference path=\"io.ts\" />\n\ninterface IOptions {\n name?: string;\n flag?: bool;\n short?: string;\n usage?: string;\n set?: (s: string) => void;\n type?: string;\n experimental?: bool;\n}\n\nclass OptionsParser {\n private DEFAULT_SHORT_FLAG = \"-\";\n private DEFAULT_LONG_FLAG = \"--\";\n\n // Find the option record for the given string. Returns null if not found.\n private findOption(arg: string) {\n\n for (var i = 0; i < this.options.length; i++) {\n\n if (arg === this.options[i].short || arg === this.options[i].name) {\n return this.options[i];\n }\n }\n\n return null;\n }\n\n public unnamed: string[] = [];\n\n public options: IOptions[] = [];\n\n constructor (public host: IIO) {\n }\n\n public printUsage() {\n this.host.printLine(\"Syntax: tsc [options] [file ..]\");\n this.host.printLine(\"\");\n this.host.printLine(\"Examples: tsc hello.ts\");\n this.host.printLine(\" tsc --out foo.js foo.ts\");\n this.host.printLine(\" tsc @args.txt\");\n this.host.printLine(\"\");\n this.host.printLine(\"Options:\");\n\n var output = [];\n var maxLength = 0;\n\n this.options = this.options.sort(function(a, b) {\n var aName = a.name.toLowerCase();\n var bName = b.name.toLowerCase();\n\n if (aName > bName) {\n return 1;\n } else if (aName < bName) {\n return -1;\n } else {\n return 0;\n }\n });\n\n // Build up output array\n for (var i = 0; i < this.options.length; i++) {\n var option = this.options[i];\n\n if (option.experimental) {\n continue;\n }\n\n if (!option.usage) {\n break;\n }\n\n var usageString = \" \";\n var type = option.type ? \" \" + option.type.toUpperCase() : \"\";\n\n if (option.short) {\n usageString += this.DEFAULT_SHORT_FLAG + option.short + type + \", \";\n }\n\n usageString += this.DEFAULT_LONG_FLAG + option.name + type;\n\n output.push([usageString, option.usage]);\n\n if (usageString.length > maxLength) {\n maxLength = usageString.length;\n }\n }\n\n output.push([\" @<file>\", \"Insert command line options and files from a file.\"]);\n\n // Print padded output\n for (var i = 0; i < output.length; i++) {\n this.host.printLine(output[i][0] + (new Array(maxLength - output[i][0].length + 3)).join(\" \") + output[i][1]);\n }\n }\n\n public option(name: string, config: IOptions, short?: string) {\n if (!config) {\n config = <any>short;\n short = null;\n }\n\n config.name = name;\n config.short = short;\n config.flag = false;\n\n this.options.push(config);\n }\n\n public flag(name: string, config: IOptions, short?: string) {\n if (!config) {\n config = <any>short;\n short = null;\n }\n\n config.name = name;\n config.short = short;\n config.flag = true\n\n this.options.push(config);\n }\n\n // Parse an arguments string\n public parseString(argString: string) {\n var position = 0;\n var tokens = argString.match(/\\s+|\"|[^\\s\"]+/g);\n\n function peek() {\n return tokens[position];\n }\n\n function consume() {\n return tokens[position++];\n }\n\n function consumeQuotedString() {\n var value = '';\n consume(); // skip opening quote.\n\n var token = peek();\n\n while (token && token !== '\"') {\n consume();\n\n value += token;\n\n token = peek();\n }\n\n consume(); // skip ending quote;\n\n return value;\n }\n\n var args: string[] = [];\n var currentArg = '';\n\n while (position < tokens.length) {\n var token = peek();\n\n if (token === '\"') {\n currentArg += consumeQuotedString();\n } else if (token.match(/\\s/)) {\n if (currentArg.length > 0) {\n args.push(currentArg);\n currentArg = '';\n }\n\n consume();\n } else {\n consume();\n currentArg += token;\n }\n }\n\n if (currentArg.length > 0) {\n args.push(currentArg);\n }\n\n this.parse(args);\n }\n\n // Parse arguments as they come from the platform: split into arguments.\n public parse(args: string[]) {\n var position = 0;\n\n function consume() {\n return args[position++];\n }\n\n while (position < args.length) {\n var current = consume();\n var match = current.match(/^(--?|@)(.*)/);\n var value = null;\n\n if (match) {\n if (match[1] === '@') {\n this.parseString(this.host.readFile(match[2]));\n } else {\n var arg = match[2];\n var option = this.findOption(arg);\n\n if (option === null) {\n this.host.printLine(\"Unknown option '\" + arg +\"'\");\n this.host.printLine(\"Use the '--help' flag to see options\");\n } else {\n if (!option.flag)\n value = consume();\n\n option.set(value);\n }\n }\n } else {\n this.unnamed.push(current);\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export enum TypeContext {\n NoTypes = 0,\n ArraySuffix = 1,\n Primitive = 2,\n Named = 4,\n AllSimpleTypes = Primitive | Named,\n AllTypes = Primitive | Named | ArraySuffix,\n }\n\n export enum ParseState {\n None,\n StartScript,\n StartStatementList,\n StartStatement,\n StartFncDecl,\n FncDeclName,\n FncDeclArgs,\n FncDeclReturnType,\n ForInit,\n ForInitAfterVar,\n ForCondStart,\n EndStmtList,\n EndScript,\n }\n\n export interface IStatementInfo {\n stmt: Statement;\n labels: ASTList;\n }\n\n export interface ILambdaArgumentContext {\n preProcessedLambdaArgs: AST;\n }\n\n export class QuickParseResult {\n constructor (public Script: Script, public endLexState: LexState) { }\n }\n\n export class Parser {\n private varLists: ASTList[] = [];\n private scopeLists: ASTList[] = [];\n private staticsLists: ASTList[] = [];\n\n private scanner: IScanner = new Scanner();\n private currentToken: Token = null;\n\n private needTerminator = false;\n\n // TODO: consolidate these\n private inFunction = false;\n private inInterfaceDecl = false;\n public currentClassDecl: NamedDeclaration = null;\n\n private inFncDecl = false; // this is only for FuncDecls - not constructors, like inFnc\n private anonId = new Identifier(\"_anonymous\");\n public style_requireSemi = false;\n public style_funcInLoop = true;\n private incremental = false;\n public errorRecovery = false;\n public outfile: ITextWriter = undefined;\n public errorCallback: (minChar: number, charLen: number, message: string, unit: number) =>void = null;\n private state: ParseState = ParseState.StartStatementList;\n private ambientModule = false;\n private ambientClass = false;\n private topLevel = true;\n private allowImportDeclaration = true;\n private currentUnitIndex = (-1);\n private prevIDTok: Token = null;\n private statementInfoStack: IStatementInfo[] = new IStatementInfo[];\n private hasTopLevelImportOrExport = false; // for imports, only true if it's a dynamic module\n private strictMode = false;\n private nestingLevel = 0;\n private prevExpr: AST = null;\n private currentClassDefinition: ClassDeclaration = null;\n private parsingClassConstructorDefinition = false;\n private parsingDeclareFile = false;\n private amdDependencies: string[] = [];\n public inferPropertiesFromThisAssignment = false;\n public requiresExtendsBlock = false;\n\n private resetStmtStack() {\n this.statementInfoStack = new IStatementInfo[];\n }\n\n private inLoop() {\n for (var j = this.statementInfoStack.length - 1; j >= 0; j--) {\n if (this.statementInfoStack[j].stmt.isLoop()) {\n return true;\n }\n }\n return false;\n }\n\n private pushStmt(stmt: Statement, labels: ASTList) {\n // allocate here to avoid always storing this information in statements\n var info = { stmt: stmt, labels: labels };\n this.statementInfoStack.push(info);\n }\n\n private popStmt(): IStatementInfo {\n return this.statementInfoStack.pop();\n }\n\n private resolveJumpTarget(jump: Jump): void {\n var resolvedTarget = AST.getResolvedIdentifierName(jump.target);\n var len = this.statementInfoStack.length;\n for (var i = len - 1; i >= 0; i--) {\n var info = this.statementInfoStack[i];\n if (jump.target) {\n if (info.labels && (info.labels.members.length > 0)) {\n for (var j = 0, labLen = info.labels.members.length; j < labLen; j++) {\n var label = <Label>info.labels.members[j];\n if (label.id.text == resolvedTarget) {\n jump.setResolvedTarget(this, info.stmt);\n return;\n }\n }\n }\n }\n else {\n if (info.stmt.isLoop()) {\n jump.setResolvedTarget(this, info.stmt);\n return;\n }\n else if ((info.stmt.nodeType == NodeType.Switch) && (jump.nodeType == NodeType.Break)) {\n jump.setResolvedTarget(this, info.stmt);\n return;\n }\n }\n }\n // no luck\n if (jump.target) {\n this.reportParseError(\"could not find enclosing statement with label \" + jump.target);\n }\n else {\n if (jump.nodeType == NodeType.Break) {\n this.reportParseError(\"break statement requires enclosing loop or switch\");\n }\n else {\n this.reportParseError(\"continue statement requires enclosing loop\");\n }\n }\n }\n\n public setErrorRecovery(outfile: ITextWriter) {\n this.outfile = outfile;\n this.errorRecovery = true;\n }\n\n public getSourceLineCol(lineCol: ILineCol, minChar: number): void {\n getSourceLineColFromMap(lineCol, minChar, this.scanner.lineMap);\n }\n\n private createRef(text: string, hasEscapeSequence: bool, minChar: number): Identifier {\n var id = new Identifier(text, hasEscapeSequence);\n id.minChar = minChar;\n return id;\n }\n\n private reportParseStyleError(message: string) {\n this.reportParseError(\"STYLE: \" + message);\n }\n\n public reportParseError(message: string, startPos = this.scanner.startPos, pos = this.scanner.pos) {\n var len = Math.max(1, pos - startPos);\n if (this.errorCallback) {\n this.errorCallback(startPos, len, message, this.currentUnitIndex);\n }\n else if (this.errorRecovery) {\n var lineCol = { line: -1, col: -1 };\n this.getSourceLineCol(lineCol, startPos);\n if (this.outfile) {\n this.outfile.WriteLine(\"// \" + this.fname + \" (\" + lineCol.line + \",\" + lineCol.col + \"): \" + message);\n }\n }\n else {\n throw new SyntaxError(this.fname + \" (\" + this.scanner.line + \",\" + this.scanner.col + \"): \" + message);\n }\n }\n\n private checkNextToken(tokenId: TokenID, errorRecoverySet: ErrorRecoverySet, errorText: string = null): void {\n this.currentToken = this.scanner.scan();\n this.checkCurrentToken(tokenId, errorRecoverySet, errorText);\n }\n\n private skip(errorRecoverySet: ErrorRecoverySet) {\n errorRecoverySet |= ErrorRecoverySet.EOF;\n var ersTok = ErrorRecoverySet.None;\n var tokenInfo = lookupToken(this.currentToken.tokenId);\n if (tokenInfo != undefined) {\n ersTok = tokenInfo.ers;\n }\n var pendingRightCurlies = 0;\n while (((ersTok & errorRecoverySet) == ErrorRecoverySet.None) ||\n (this.currentToken.tokenId == TokenID.CloseBrace) && (pendingRightCurlies > 0)) {\n if (this.currentToken.tokenId == TokenID.OpenBrace) {\n pendingRightCurlies++;\n }\n else if (this.currentToken.tokenId == TokenID.CloseBrace) {\n pendingRightCurlies--;\n }\n this.currentToken = this.scanner.scan();\n ersTok = ErrorRecoverySet.None;\n tokenInfo = lookupToken(this.currentToken.tokenId);\n if (tokenInfo != undefined) {\n ersTok = tokenInfo.ers;\n }\n // TODO: regex rescan \n }\n }\n\n private checkCurrentToken(tokenId: TokenID, errorRecoverySet: ErrorRecoverySet, errorText: string = null): void {\n if (this.currentToken.tokenId != tokenId) {\n errorText = errorText == null ? (\"Expected '\" + tokenTable[tokenId].text + \"'\") : errorText;\n this.reportParseError(errorText);\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n }\n }\n else {\n this.currentToken = this.scanner.scan();\n }\n }\n\n private pushDeclLists() {\n this.staticsLists.push(new ASTList());\n this.varLists.push(new ASTList());\n this.scopeLists.push(new ASTList());\n }\n\n private popDeclLists() {\n this.staticsLists.pop();\n this.varLists.pop();\n this.scopeLists.pop();\n }\n\n private topVarList() {\n return this.varLists[this.varLists.length - 1];\n }\n\n private topScopeList() {\n return this.scopeLists[this.scopeLists.length - 1];\n }\n\n private topStaticsList() {\n return this.staticsLists[this.staticsLists.length - 1];\n }\n\n private parseComment(comment: CommentToken) {\n if (comment) {\n var c: Comment = new Comment(comment.value, comment.isBlock, comment.endsLine);\n c.minChar = comment.startPos;\n c.limChar = comment.startPos + comment.value.length;\n var lineCol = { line: -1, col: -1 };\n this.getSourceLineCol(lineCol, c.minChar);\n c.minLine = lineCol.line;\n this.getSourceLineCol(lineCol, c.limChar);\n c.limLine = lineCol.line;\n\n if (!comment.isBlock && comment.value.length > 3 && comment.value.substring(0, 3) == \"///\") {\n var dependencyPath = getAdditionalDependencyPath(comment.value);\n\n if (dependencyPath) {\n this.amdDependencies.push(dependencyPath);\n }\n\n if (getImplicitImport(comment.value)) {\n this.hasTopLevelImportOrExport = true;\n }\n }\n\n return c;\n }\n else {\n return null;\n }\n }\n\n private parseCommentsInner(comments: CommentToken[]) {\n if (comments) {\n var commentASTs: Comment[] = new Comment[];\n for (var i = 0; i < comments.length; i++) {\n commentASTs.push(this.parseComment(comments[i]));\n }\n return commentASTs;\n } else {\n return null;\n }\n }\n\n private parseComments() {\n var comments = this.scanner.getComments();\n return this.parseCommentsInner(comments);\n }\n\n private parseCommentsForLine(line: number) {\n var comments = this.scanner.getCommentsForLine(line);\n\n return this.parseCommentsInner(comments);\n }\n\n private combineComments(comment1: Comment[], comment2: Comment[]) {\n if (comment1 == null) {\n return comment2;\n }\n else if (comment2 == null) {\n return comment1;\n }\n else {\n return comment1.concat(comment2);\n }\n }\n\n private parseEnumDecl(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers): ModuleDeclaration {\n var leftCurlyCount = this.scanner.leftCurlyCount;\n var rightCurlyCount = this.scanner.rightCurlyCount;\n\n var name: Identifier = null;\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n name = Identifier.fromToken(this.currentToken);\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n else {\n this.reportParseError(\"Enum declaration requires identifier\");\n if (this.errorRecovery) {\n name = new MissingIdentifier();\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.startPos;\n name.flags |= ASTFlags.Error;\n }\n }\n\n var membersMinChar = this.scanner.startPos;\n this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.ID);\n this.pushDeclLists();\n var members = new ASTList();\n members.minChar = membersMinChar;\n var mapDecl = new VarDecl(new Identifier(\"_map\"), 0);\n mapDecl.varFlags |= VarFlags.Exported;\n mapDecl.varFlags |= VarFlags.Private;\n\n // REVIEW: Is this still necessary?\n mapDecl.varFlags |= (VarFlags.Property | VarFlags.Public);\n mapDecl.init = new UnaryExpression(NodeType.ArrayLit, null);\n members.append(mapDecl);\n var lastValue: NumberLiteral = null;\n for (; ;) {\n var minChar = this.scanner.startPos;\n var limChar;\n var memberName: Identifier = null;\n var memberValue: AST = null;\n var preComments = null;\n var postComments = null;\n\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToIDName(this.currentToken)) {\n memberName = Identifier.fromToken(this.currentToken);\n memberName.minChar = this.scanner.startPos;\n memberName.limChar = this.scanner.pos;\n }\n else if (this.currentToken.tokenId == TokenID.CloseBrace) {\n break;\n }\n else {\n this.reportParseError(\"Expected identifer of enum member\");\n if (this.errorRecovery) {\n memberName = new MissingIdentifier();\n memberName.minChar = this.scanner.startPos;\n memberName.limChar = this.scanner.startPos;\n memberName.flags |= ASTFlags.Error;\n }\n }\n\n limChar = this.scanner.pos;\n preComments = this.parseComments();\n this.currentToken = this.scanner.scan();\n postComments = this.parseComments();\n\n if (this.currentToken.tokenId == TokenID.Equals) {\n this.currentToken = this.scanner.scan();\n memberValue = this.parseExpr(errorRecoverySet, OperatorPrecedence.Comma, true,\n TypeContext.NoTypes);\n lastValue = <NumberLiteral>memberValue;\n limChar = memberValue.limChar;\n }\n else {\n if (lastValue == null) {\n memberValue = new NumberLiteral(0);\n lastValue = <NumberLiteral>memberValue;\n }\n else {\n memberValue = new NumberLiteral(lastValue.value + 1);\n lastValue = <NumberLiteral>memberValue;\n }\n var map: BinaryExpression =\n new BinaryExpression(NodeType.Asg,\n new BinaryExpression(NodeType.Index,\n new Identifier(\"_map\"),\n memberValue),\n new StringLiteral('\"' + memberName.actualText + '\"'));\n members.append(map);\n }\n var member = new VarDecl(memberName, this.nestingLevel);\n member.minChar = minChar;\n member.limChar = limChar;\n member.init = memberValue;\n // Note: Leave minChar, limChar as \"-1\" on typeExpr as this is a parsing artifact.\n member.typeExpr = new TypeReference(this.createRef(name.actualText, name.hasEscapeSequence, -1), 0);\n member.varFlags |= (VarFlags.Readonly | VarFlags.Property);\n if (memberValue.nodeType == NodeType.NumberLit) {\n member.varFlags |= VarFlags.Constant;\n }\n member.preComments = preComments;\n members.append(member);\n member.postComments = postComments;\n // all enum members are exported\n member.varFlags |= VarFlags.Exported;\n\n if (this.currentToken.tokenId == TokenID.Comma) {\n this.currentToken = this.scanner.scan();\n member.postComments = this.combineComments(member.postComments, this.parseCommentsForLine(this.scanner.prevLine));\n if ((this.currentToken.tokenId == TokenID.Identifier) || (convertTokToIDName(this.currentToken))) {\n continue;\n }\n }\n break;\n }\n var endingToken = new ASTSpan();\n endingToken.minChar = this.scanner.startPos;\n endingToken.limChar = this.scanner.pos;\n\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n members.limChar = this.scanner.lastTokenLimChar();\n var modDecl = new ModuleDeclaration(name, members, this.topVarList(), this.topScopeList(), endingToken);\n modDecl.modFlags |= ModuleFlags.IsEnum;\n this.popDeclLists();\n\n modDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n modDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n return modDecl;\n }\n\n private parseDottedName(enclosedList: AST[]): void {\n this.currentToken = this.scanner.scan();\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n var id = Identifier.fromToken(this.currentToken);\n id.preComments = this.parseComments();\n enclosedList[enclosedList.length] = id;\n id.minChar = this.scanner.startPos;\n id.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.Dot) {\n this.parseDottedName(enclosedList);\n }\n }\n else {\n this.reportParseError(\"need identifier after '.'\");\n }\n }\n\n // REVIEW: This is much more lenient than the spec - we're basically just checking to see if the\n // path is rooted or contains an extension, not if it could potentially be a bogus file path\n private isValidImportPath(importPath: string) {\n importPath = stripQuotes(importPath);\n\n if (!importPath ||\n importPath.indexOf(':') != -1 || \n importPath.indexOf('\\\\') != -1 ||\n //(importPath.indexOf('.') != -1 && importPath.charAt(0) != '.') ||\n importPath.charAt(0) == '/') {\n return false;\n }\n return true;\n }\n\n private parseImportDeclaration(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers): ImportDeclaration {\n\n var name: Identifier = null;\n var alias: AST = null;\n var importDecl: ImportDeclaration = null;\n var minChar = this.scanner.startPos;\n var isDynamicImport = false;\n\n this.currentToken = this.scanner.scan();\n\n if (this.currentToken.tokenId == TokenID.Identifier || convertTokToID(this.currentToken, this.strictMode)) {\n name = Identifier.fromToken(this.currentToken);\n }\n else {\n this.reportParseError(\"Expected identifer after 'import'\");\n name = new MissingIdentifier();\n }\n\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.pos;\n\n this.currentToken = this.scanner.scan();\n\n this.checkCurrentToken(TokenID.Equals, errorRecoverySet | ErrorRecoverySet.ID);\n\n var aliasPreComments = this.parseComments();\n\n var limChar;\n if (this.currentToken.tokenId == TokenID.Identifier || convertTokToID(this.currentToken, this.strictMode)) {\n\n if (this.currentToken.tokenId == TokenID.Module) {\n limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.OpenParen) {\n this.currentToken = this.scanner.scan();\n\n if (this.currentToken.tokenId == TokenID.StringLiteral || this.currentToken.tokenId == TokenID.Identifier || convertTokToID(this.currentToken, this.strictMode)) {\n\n if (this.currentToken.tokenId == TokenID.StringLiteral) {\n\n if (this.topLevel) {\n this.hasTopLevelImportOrExport = true;\n } else if (!this.allowImportDeclaration) {\n this.reportParseError(\"Import declaration of external module is permitted only in global or top level dynamic modules\");\n }\n\n var aliasText = this.currentToken.getText();\n alias = Identifier.fromToken(this.currentToken);\n alias.minChar = this.scanner.startPos;\n alias.limChar = this.scanner.pos;\n\n if (!this.isValidImportPath((<Identifier>alias).text)) {\n this.reportParseError(\"Invalid import path\");\n }\n\n isDynamicImport = true;\n this.currentToken = this.scanner.scan();\n \n alias.preComments = aliasPreComments;\n }\n else {\n alias = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n OperatorPrecedence.Assignment, true,\n TypeContext.NoTypes);\n \n alias.preComments = aliasPreComments;\n }\n }\n\n limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.ID);\n\n if (alias) {\n alias.postComments = this.parseComments();\n }\n }\n }\n else {\n alias = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n OperatorPrecedence.Assignment, true,\n TypeContext.NoTypes);\n limChar = this.scanner.pos; // Include semicolon if needed\n }\n }\n else {\n this.reportParseError(\"Expected module name\");\n alias = new MissingIdentifier();\n alias.minChar = this.scanner.startPos;\n if (this.currentToken.tokenId == TokenID.Semicolon) {\n alias.limChar = this.scanner.startPos;\n } else {\n alias.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n alias.flags |= ASTFlags.Error;\n limChar = alias.limChar;\n }\n\n importDecl = new ImportDeclaration(name, alias);\n importDecl.isDynamicImport = isDynamicImport;\n\n importDecl.minChar = minChar;\n importDecl.limChar = limChar;\n\n return importDecl;\n }\n\n private parseModuleDecl(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers, preComments: Comment[]): ModuleDeclaration {\n var leftCurlyCount = this.scanner.leftCurlyCount;\n var rightCurlyCount = this.scanner.rightCurlyCount;\n\n var svAmbient = this.ambientModule;\n var svTopLevel = this.topLevel;\n this.topLevel = false;\n if (this.parsingDeclareFile || svAmbient || hasFlag(modifiers, Modifiers.Ambient)) {\n this.ambientModule = true;\n }\n\n this.currentToken = this.scanner.scan();\n var name: AST = null;\n var enclosedList: AST[] = null;\n this.pushDeclLists();\n var minChar = this.scanner.startPos;\n var isDynamicMod = false;\n\n if ((this.currentToken.tokenId == TokenID.Identifier) || (this.currentToken.tokenId == TokenID.StringLiteral) || (!isPrimitiveTypeToken(this.currentToken) && convertTokToID(this.currentToken, this.strictMode))) {\n var nameText = this.currentToken.getText();\n\n if (this.currentToken.tokenId == TokenID.StringLiteral) {\n isDynamicMod = true;\n if (!this.ambientModule) {\n this.reportParseError(\"Only ambient dynamic modules may have string literal names\");\n }\n\n if (!svTopLevel) {\n this.reportParseError(\"Dynamic modules may not be nested within other modules\");\n }\n }\n\n name = Identifier.fromToken(this.currentToken);\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.pos;\n\n this.currentToken = this.scanner.scan();\n }\n else if (this.currentToken.tokenId == TokenID.OpenBrace) {\n this.reportParseError(\"Module name missing\");\n name = new Identifier(\"\");\n // \"fake\" position of where the ID would be\n name.minChar = minChar;\n name.limChar = minChar;\n }\n\n if (this.currentToken.tokenId == TokenID.Dot) {\n enclosedList = new AST[];\n this.parseDottedName(enclosedList);\n }\n\n if (name == null) {\n name = new MissingIdentifier();\n }\n\n var moduleBody = new ASTList();\n var bodyMinChar = this.scanner.startPos;\n this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.ID);\n\n if (svTopLevel && isDynamicMod) {\n this.allowImportDeclaration = true;\n } else {\n this.allowImportDeclaration = false;\n }\n this.parseStatementList(\n errorRecoverySet | ErrorRecoverySet.RCurly, moduleBody,\n /*sourceElements:*/ true, /*noLeadingCase:*/ true, AllowedElements.Global, modifiers);\n moduleBody.minChar = bodyMinChar;\n moduleBody.limChar = this.scanner.pos;\n\n var endingToken = new ASTSpan();\n endingToken.minChar = this.scanner.startPos;\n endingToken.limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n var limChar = this.scanner.lastTokenLimChar();\n var moduleDecl: ModuleDeclaration;\n\n this.allowImportDeclaration = svTopLevel;\n\n if (enclosedList && (enclosedList.length > 0)) {\n var len = enclosedList.length;\n var innerName = <Identifier>enclosedList[len - 1];\n var innerDecl = new ModuleDeclaration(innerName, moduleBody, this.topVarList(),\n this.topScopeList(), endingToken);\n innerDecl.preComments = preComments;\n\n if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n innerDecl.modFlags |= ModuleFlags.Ambient;\n }\n\n innerDecl.modFlags |= ModuleFlags.Exported;\n\n // REVIEW: will also possibly need to re-parent comments as well\n innerDecl.minChar = minChar;\n innerDecl.limChar = limChar;\n\n this.popDeclLists();\n var outerModBod: ASTList;\n for (var i = len - 2; i >= 0; i--) {\n outerModBod = new ASTList();\n outerModBod.append(innerDecl);\n innerName = <Identifier>enclosedList[i];\n innerDecl = new ModuleDeclaration(innerName, outerModBod, new ASTList(),\n new ASTList(), endingToken);\n outerModBod.minChar = innerDecl.minChar = minChar;\n outerModBod.limChar = innerDecl.limChar = limChar;\n\n if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n innerDecl.modFlags |= ModuleFlags.Ambient;\n }\n\n innerDecl.modFlags |= ModuleFlags.Exported;\n }\n outerModBod = new ASTList();\n outerModBod.append(innerDecl);\n outerModBod.minChar = minChar;\n outerModBod.limChar = limChar;\n moduleDecl = new ModuleDeclaration(<Identifier>name, outerModBod, new ASTList(),\n new ASTList(), endingToken);\n }\n else {\n moduleDecl = new ModuleDeclaration(<Identifier>name, moduleBody, this.topVarList(), this.topScopeList(), endingToken);\n moduleDecl.preComments = preComments;\n this.popDeclLists();\n }\n\n if (this.parsingDeclareFile || svAmbient || hasFlag(modifiers, Modifiers.Ambient)) {\n moduleDecl.modFlags |= ModuleFlags.Ambient;\n }\n if (svAmbient || hasFlag(modifiers, Modifiers.Exported)) {\n moduleDecl.modFlags |= ModuleFlags.Exported;\n }\n if (isDynamicMod) {\n moduleDecl.modFlags |= ModuleFlags.IsDynamic;\n }\n\n this.ambientModule = svAmbient;\n\n this.topLevel = svTopLevel;\n moduleDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n moduleDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n moduleDecl.limChar = moduleBody.limChar;\n return moduleDecl;\n }\n\n private parseTypeReferenceTail(errorRecoverySet: ErrorRecoverySet, minChar: number, term: AST): TypeReference {\n var result = new TypeReference(term, 0);\n result.minChar = minChar;\n while (this.currentToken.tokenId == TokenID.OpenBracket) {\n this.currentToken = this.scanner.scan();\n result.arrayCount++;\n this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet | ErrorRecoverySet.LBrack);\n }\n result.limChar = this.scanner.lastTokenLimChar();\n return result;\n }\n\n // REVIEW: Consider renaming to parseTypeName.\n private parseNamedType(errorRecoverySet: ErrorRecoverySet, minChar: number, term: AST, tail: bool): AST {\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.Dot) {\n var curpos = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n // Don't allow reserved words if immediately after a new line and error recovery is enabled\n if ((this.currentToken.tokenId == TokenID.Identifier) || ((!this.errorRecovery || !this.scanner.lastTokenHadNewline()) && convertTokToID(this.currentToken, this.strictMode))) {\n var op2 = Identifier.fromToken(this.currentToken);\n op2.minChar = this.scanner.startPos;\n op2.limChar = this.scanner.pos;\n var dotNode = new BinaryExpression(NodeType.Dot, term, op2);\n dotNode.minChar = term.minChar;\n dotNode.limChar = op2.limChar;\n return this.parseNamedType(errorRecoverySet, minChar,\n dotNode, tail);\n }\n else {\n this.reportParseError(\"need identifier after '.'\");\n if (this.errorRecovery) {\n term.flags |= ASTFlags.DotLHS;\n // We set \"limChar\" to be slightly innacurate for completion list behavior\n // (last AST node from \"quickParse\" will match DotLHS and be at end of file position)\n // This is to match the behavior of TokenId.Dot processing in parsePostfixOperators.\n term.limChar = this.scanner.lastTokenLimChar();\n return term;\n }\n else {\n var eop2 = new MissingIdentifier();\n eop2.minChar = this.scanner.pos;\n eop2.limChar = this.scanner.pos;\n var edotNode = new BinaryExpression(NodeType.Dot, term, eop2);\n edotNode.flags |= ASTFlags.Error;\n edotNode.minChar = term.minChar;\n edotNode.limChar = eop2.limChar;\n return this.parseNamedType(errorRecoverySet, minChar,\n edotNode, tail);\n }\n }\n }\n else {\n if (tail) {\n return this.parseTypeReferenceTail(errorRecoverySet, minChar, term);\n }\n else {\n return term;\n }\n }\n }\n\n // REVIEW: Reconsider renaming this to parseType to match the grammar.\n private parseTypeReference(errorRecoverySet: ErrorRecoverySet, allowVoid: bool): AST {\n var minChar = this.scanner.startPos;\n var isConstructorMember = false;\n\n switch (this.currentToken.tokenId) {\n case TokenID.Void:\n if (!allowVoid) {\n this.reportParseError(\"void not a valid type in this context\");\n }\n // Intentional fall-through\n case TokenID.Any:\n case TokenID.Number:\n case TokenID.Bool:\n case TokenID.String: {\n var text = tokenTable[this.currentToken.tokenId].text;\n var predefinedIdentifier = new Identifier(text);\n predefinedIdentifier.minChar = minChar;\n predefinedIdentifier.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n return this.parseTypeReferenceTail(errorRecoverySet, minChar, predefinedIdentifier);\n }\n\n case TokenID.Identifier:\n var ident = this.createRef(this.currentToken.getText(), (<IdentifierToken>this.currentToken).hasEscapeSequence, minChar);\n ident.limChar = this.scanner.pos;\n return this.parseNamedType(errorRecoverySet, minChar, ident, true);\n\n case TokenID.OpenBrace:\n return this.parseObjectType(minChar, errorRecoverySet);\n\n case TokenID.New:\n this.currentToken = this.scanner.scan();\n // can't use chkCurrentTok, since we don't want to advance the token\n if (this.currentToken.tokenId != TokenID.OpenParen) {\n this.reportParseError(\"Expected '('\");\n }\n else {\n isConstructorMember = true;\n // fall through...\n }\n\n case TokenID.OpenParen: {\n // ( formals ) => type\n var formals = new ASTList();\n var variableArgList =\n this.parseFormalParameterList(errorRecoverySet | ErrorRecoverySet.RParen,\n formals, false, true, false, false, false, false, null, true);\n this.checkCurrentToken(TokenID.EqualsGreaterThan, errorRecoverySet);\n var returnType = this.parseTypeReference(errorRecoverySet, true);\n var funcDecl = new FuncDecl(null, null, false, formals, null, null, null,\n NodeType.FuncDecl);\n funcDecl.returnTypeAnnotation = returnType;\n funcDecl.variableArgList = variableArgList;\n funcDecl.fncFlags |= FncFlags.Signature;\n\n if (isConstructorMember) {\n funcDecl.fncFlags |= FncFlags.ConstructMember;\n funcDecl.hint = \"_construct\";\n funcDecl.classDecl = null;\n }\n funcDecl.minChar = minChar;\n return this.parseTypeReferenceTail(errorRecoverySet, minChar, funcDecl);\n }\n\n default:\n this.reportParseError(\"Expected type name\");\n var etr = new TypeReference(null, 0);\n etr.flags |= ASTFlags.Error;\n etr.minChar = this.scanner.pos;\n etr.limChar = this.scanner.pos;\n return etr;\n }\n }\n\n private parseObjectType(minChar: number, errorRecoverySet: ErrorRecoverySet): TypeReference {\n this.currentToken = this.scanner.scan();\n\n var members = new ASTList();\n members.minChar = minChar;\n\n var prevInInterfaceDecl = this.inInterfaceDecl;\n this.inInterfaceDecl = true;\n this.parseTypeMemberList(errorRecoverySet | ErrorRecoverySet.RCurly, members);\n this.inInterfaceDecl = prevInInterfaceDecl;\n\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n // REVIEW: We're parsing an ObjectType, but we give a NodeType of Interface here.\n var interfaceDecl = new InterfaceDeclaration(\n this.anonId, members, /*extends:*/ null, /*implementsL*/ null);\n\n interfaceDecl.minChar = minChar;\n interfaceDecl.limChar = members.limChar; // \"}\"\n\n return this.parseTypeReferenceTail(errorRecoverySet, minChar, interfaceDecl);\n }\n\n private parseFunctionBlock(errorRecoverySet: ErrorRecoverySet,\n allowedElements: AllowedElements,\n parentModifiers: Modifiers,\n bod: ASTList,\n bodMinChar: number): void {\n this.state = ParseState.StartStatementList;\n this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.StmtStart);\n var savedInFunction = this.inFunction;\n this.inFunction = true;\n this.parseStatementList(\n errorRecoverySet | ErrorRecoverySet.RCurly | ErrorRecoverySet.StmtStart,\n bod, /*sourceElements:*/ true, /*noLeadingCase:*/ false, allowedElements, parentModifiers);\n bod.minChar = bodMinChar;\n bod.limChar = this.scanner.pos;\n this.inFunction = savedInFunction;\n var ec = new EndCode();\n ec.minChar = bod.limChar;\n ec.limChar = ec.minChar;\n bod.append(ec);\n }\n\n private parseFunctionStatements(errorRecoverySet: ErrorRecoverySet,\n name: Identifier,\n isConstructor: bool,\n isMethod: bool,\n args: ASTList,\n allowedElements: AllowedElements,\n minChar: number,\n requiresSignature: bool,\n parentModifiers: Modifiers) {\n\n this.pushDeclLists();\n // start new statement stack\n var svStmtStack = this.statementInfoStack;\n this.resetStmtStack();\n\n var bod: ASTList = null;\n var wasShorthand = false;\n var isAnonLambda = false;\n var limChar: number;\n\n if (requiresSignature) {\n // If we require a signature, but they provided a block, then give an error, but\n // still consume the block.\n limChar = this.scanner.pos;\n if (this.currentToken.tokenId === TokenID.OpenBrace) {\n this.reportParseError(\"Function declarations are not permitted within interfaces, ambient modules or classes\")\n bod = new ASTList();\n var bodMinChar = this.scanner.startPos;\n\n this.parseFunctionBlock(errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar);\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n // If there's also a semicolon, then just skip over it. We don't want to report an \n // additional error here.\n if (this.currentToken.tokenId === TokenID.Semicolon) {\n this.currentToken = this.scanner.scan();\n }\n }\n else {\n this.checkCurrentToken(TokenID.Semicolon, errorRecoverySet, \"Expected ';'\");\n }\n }\n else {\n bod = new ASTList();\n var bodMinChar = this.scanner.startPos;\n if (this.currentToken.tokenId == TokenID.EqualsGreaterThan) {\n if (isMethod) {\n this.reportParseError(\"'=>' may not be used for class methods\");\n }\n wasShorthand = true;\n this.currentToken = this.scanner.scan();\n }\n\n if (wasShorthand && this.currentToken.tokenId != TokenID.OpenBrace) {\n var retExpr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n OperatorPrecedence.Assignment, true,\n TypeContext.NoTypes);\n var retStmt = new ReturnStatement();\n retStmt.returnExpression = retExpr;\n retStmt.minChar = retExpr.minChar;\n retStmt.limChar = retExpr.limChar;\n bod.minChar = bodMinChar;\n bod.append(retStmt);\n }\n else {\n isAnonLambda = wasShorthand;\n this.parseFunctionBlock(errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar);\n }\n\n limChar = this.scanner.pos;\n }\n\n var funcDecl = new FuncDecl(name, bod, isConstructor, args, this.topVarList(),\n this.topScopeList(), this.topStaticsList(), NodeType.FuncDecl);\n this.popDeclLists();\n var scopeList = this.topScopeList();\n scopeList.append(funcDecl);\n var staticFuncDecl = false;\n\n if (!requiresSignature) {\n if (!wasShorthand || isAnonLambda) {\n funcDecl.endingToken = new ASTSpan();\n funcDecl.endingToken.minChar = this.scanner.startPos;\n funcDecl.endingToken.limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n if (isAnonLambda) {\n funcDecl.fncFlags |= FncFlags.IsFatArrowFunction;\n }\n }\n else {\n funcDecl.fncFlags |= FncFlags.IsFatArrowFunction;\n funcDecl.endingToken = new ASTSpan();\n\n funcDecl.endingToken.minChar = bod.members[0].minChar;\n funcDecl.endingToken.limChar = bod.members[0].limChar;\n }\n }\n funcDecl.minChar = minChar;\n funcDecl.limChar = limChar;\n\n if (!requiresSignature) {\n funcDecl.fncFlags |= FncFlags.Definition;\n }\n\n this.statementInfoStack = svStmtStack;\n return funcDecl;\n }\n\n private transformAnonymousArgsIntoFormals(formals: ASTList, argList: AST) : bool {\n\n var translateBinExOperand = (operand: AST) : bool => {\n if (operand.nodeType == NodeType.Comma) {\n return this.transformAnonymousArgsIntoFormals(formals, operand);\n }\n else if (operand.nodeType == NodeType.Name || operand.nodeType == NodeType.Asg) {\n var opArg = operand.nodeType == NodeType.Asg ? (<BinaryExpression>operand).operand1 : operand;\n\n var arg = new ArgDecl(<Identifier>opArg);\n arg.preComments = opArg.preComments;\n arg.postComments = opArg.postComments;\n arg.minChar = operand.minChar;\n arg.limChar = operand.limChar;\n\n if (hasFlag(opArg.flags, ASTFlags.PossibleOptionalParameter)) {\n arg.isOptional = true;\n }\n\n if (operand.nodeType == NodeType.Asg) {\n arg.init = (<BinaryExpression>operand).operand2;\n }\n\n formals.append(arg);\n\n return arg.isOptional || arg.init;\n }\n else {\n this.reportParseError(\"Invalid lambda argument\");\n }\n return false;\n }\n\n if (argList) {\n if (argList.nodeType == NodeType.Comma) {\n var commaList = <BinaryExpression> argList;\n if (commaList.operand1.isParenthesized) { \n this.reportParseError(\"Invalid lambda argument\", commaList.operand1.minChar, commaList.operand1.limChar);\n }\n if (commaList.operand2.isParenthesized) { \n this.reportParseError(\"Invalid lambda argument\", commaList.operand2.minChar, commaList.operand2.limChar);\n }\n var isOptional = translateBinExOperand(commaList.operand1);\n isOptional = translateBinExOperand(commaList.operand2) || isOptional;\n return isOptional;\n }\n else {\n return translateBinExOperand(argList);\n }\n }\n }\n\n private parseFormalParameterList(errorRecoverySet: ErrorRecoverySet,\n formals: ASTList,\n isClassConstr: bool,\n isSig: bool,\n isIndexer: bool,\n isGetter: bool,\n isSetter: bool,\n isLambda: bool,\n preProcessedLambdaArgs: AST,\n expectClosingRParen: bool): bool \n {\n\n formals.minChar = this.scanner.startPos; // '(' or '['\n if (isIndexer) {\n this.currentToken = this.scanner.scan();\n }\n else if (!isLambda) {\n this.checkCurrentToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.RParen);\n }\n var sawEllipsis = false;\n var firstArg = true;\n var hasOptional = false;\n var haveFirstArgID = false;\n\n // if preProcessedLambdaArgs is \"true\", we either have a typeless argument list, or we have\n // a single identifier node and the current token is the ':' before a typereference\n if (isLambda && preProcessedLambdaArgs && preProcessedLambdaArgs.nodeType != NodeType.EmptyExpr) {\n hasOptional = this.transformAnonymousArgsIntoFormals(formals, preProcessedLambdaArgs);\n haveFirstArgID = true;\n }\n\n while (true) {\n var munchedArg = false;\n var argFlags = VarFlags.None;\n var argMinChar = this.scanner.startPos;\n\n if (this.inferPropertiesFromThisAssignment && this.currentToken.tokenId == TokenID.This) {\n if (!isClassConstr) {\n this.reportParseError(\"Instance property declarations using 'this' may only be used in class constructors\");\n }\n this.currentToken = this.scanner.scan(); // consume the '.'\n\n argFlags |= (VarFlags.Public | VarFlags.Property);\n if (this.currentClassDefinition) {\n this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n }\n }\n if (this.currentToken.tokenId == TokenID.Public) {\n argFlags |= (VarFlags.Public | VarFlags.Property);\n\n if (this.currentClassDefinition) {\n this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n }\n }\n else if (this.currentToken.tokenId == TokenID.Private) {\n argFlags |= (VarFlags.Private | VarFlags.Property);\n\n if (this.currentClassDefinition) {\n this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n }\n }\n else if (this.currentToken.tokenId == TokenID.Static && isClassConstr) {\n this.reportParseError(\"Static properties can not be declared as parameter properties\");\n this.currentToken = this.scanner.scan();\n }\n\n if (argFlags != VarFlags.None) {\n if (!isClassConstr) {\n this.reportParseError(\"only constructor parameters can be properties\");\n }\n this.currentToken = this.scanner.scan();\n\n if (isModifier(this.currentToken)) { \n this.reportParseError(\"Multiple modifiers may not be applied to parameters\");\n this.currentToken = this.scanner.scan();\n }\n\n if (this.inferPropertiesFromThisAssignment && this.currentToken.tokenId == TokenID.This) {\n if (!isClassConstr) {\n this.reportParseError(\"Instance property declarations using 'this' may only be used in class constructors\");\n }\n this.currentToken = this.scanner.scan(); // consume the '.'\n this.currentToken = this.scanner.scan();\n }\n }\n else if (this.currentToken.tokenId == TokenID.DotDotDot) {\n sawEllipsis = true;\n this.currentToken = this.scanner.scan();\n\n if (!(this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n this.reportParseError(\"'...' parameters require both a parameter name and an array type annotation to be specified\");\n sawEllipsis = false; // Do not treat this parameter as vararg\n }\n }\n\n var argId: Identifier = null;\n\n if (!haveFirstArgID && (this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n argId = Identifier.fromToken(this.currentToken);\n argId.minChar = this.scanner.startPos;\n argId.limChar = this.scanner.pos;\n }\n\n if (haveFirstArgID || argId) {\n munchedArg = true;\n var type: AST = null;\n var arg: ArgDecl = null;\n\n if (haveFirstArgID && formals.members.length) {\n arg = <ArgDecl>formals.members[formals.members.length - 1];\n\n if (arg.isOptional) {\n hasOptional = true;\n }\n }\n else {\n arg = new ArgDecl(argId);\n\n if (isGetter) {\n this.reportParseError(\"Property getters may not take any arguments\");\n }\n\n if (isSetter && !firstArg) {\n this.reportParseError(\"Property setters may only take one argument\");\n }\n\n arg.minChar = argMinChar;\n arg.preComments = this.parseComments();\n this.currentToken = this.scanner.scan();\n }\n\n if (this.currentToken.tokenId == TokenID.Question) {\n arg.isOptional = true;\n hasOptional = true;\n this.currentToken = this.scanner.scan();\n }\n\n if (this.currentToken.tokenId == TokenID.Colon) {\n this.currentToken = this.scanner.scan();\n type = this.parseTypeReference(errorRecoverySet, false);\n }\n\n // check for default parameter\n // REVIEW: In the case of a typed reference, assume that parseTypeReference or one\n // of its children in the call graph advanced tok\n if (this.currentToken.tokenId == TokenID.Equals) {\n if (isSig) {\n this.reportParseError(\"Arguments in signatures may not have default values\");\n }\n\n hasOptional = true;\n this.currentToken = this.scanner.scan();\n arg.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, false,\n TypeContext.NoTypes);\n\n }\n\n if (hasOptional && !arg.isOptionalArg() && !sawEllipsis) {\n this.reportParseError(\"Optional parameters may only be followed by other optional parameters\");\n }\n\n if (sawEllipsis && arg.isOptionalArg()) {\n this.reportParseError(\"Varargs may not be optional or have default parameters\");\n }\n\n if (sawEllipsis && !type) {\n // Ellipsis is missing a type definition\n this.reportParseError(\"'...' parameters require both a parameter name and an array type annotation to be specified\");\n }\n\n // REVIEW: Ok for lambdas?\n arg.postComments = this.parseComments();\n arg.typeExpr = type;\n arg.limChar = this.scanner.lastTokenLimChar();\n arg.varFlags |= argFlags;\n if (!haveFirstArgID) {\n formals.append(arg);\n }\n else {\n haveFirstArgID = false;\n }\n }\n firstArg = false;\n if (this.currentToken.tokenId == TokenID.Comma) {\n if ((munchedArg) && (!sawEllipsis)) {\n this.currentToken = this.scanner.scan();\n continue;\n }\n else {\n this.reportParseError(\"Unexpected ',' in argument list\");\n if (this.errorRecovery) {\n this.currentToken = this.scanner.scan();\n continue;\n }\n }\n }\n else {\n break;\n }\n }\n\n if (isIndexer) {\n this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet | ErrorRecoverySet.LCurly | ErrorRecoverySet.SColon);\n }\n else if (expectClosingRParen) {\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly | ErrorRecoverySet.SColon);\n }\n formals.limChar = this.scanner.lastTokenLimChar(); // ')' or ']'\n return sawEllipsis;\n }\n\n private parseFncDecl(errorRecoverySet: ErrorRecoverySet,\n isDecl: bool,\n requiresSignature: bool,\n isMethod: bool,\n methodName: Identifier,\n indexer: bool,\n isStatic: bool,\n markedAsAmbient: bool,\n modifiers: Modifiers,\n lambdaArgContext: ILambdaArgumentContext,\n expectClosingRParen: bool): AST {\n\n var leftCurlyCount = this.scanner.leftCurlyCount;\n var rightCurlyCount = this.scanner.rightCurlyCount;\n\n var prevInConstr = this.parsingClassConstructorDefinition;\n this.parsingClassConstructorDefinition = false;\n\n var name: Identifier = null;\n var fnMin = this.scanner.startPos;\n var minChar = this.scanner.pos;\n var prevNestingLevel = this.nestingLevel;\n var preComments = this.parseComments();\n var isLambda = !!lambdaArgContext;\n this.nestingLevel = 0;\n if ((!this.style_funcInLoop) && this.inLoop()) {\n this.reportParseStyleError(\"function declaration in loop\");\n }\n if (!isMethod && !isStatic && !indexer && !lambdaArgContext) {\n // past function keyword\n this.currentToken = this.scanner.scan();\n this.state = ParseState.StartFncDecl;\n if ((this.currentToken.tokenId != TokenID.Identifier) && (!convertTokToID(this.currentToken, this.strictMode))) {\n if (isDecl) {\n this.reportParseError(\"Function declaration must include identifier\");\n\n this.nestingLevel = prevNestingLevel;\n return new IncompleteAST(fnMin, this.scanner.pos);\n }\n }\n else {\n name = Identifier.fromToken(this.currentToken);\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n }\n else {\n if (methodName) {\n name = methodName;\n }\n }\n\n this.state = ParseState.FncDeclName;\n var args: ASTList = new ASTList();\n var variableArgList = false;\n var isOverload = false;\n var isGetter = hasFlag(modifiers, Modifiers.Getter);\n var isSetter = hasFlag(modifiers, Modifiers.Setter);\n if ((this.currentToken.tokenId == TokenID.OpenParen) || (indexer && (this.currentToken.tokenId == TokenID.OpenBracket)) || (lambdaArgContext && (lambdaArgContext.preProcessedLambdaArgs || this.currentToken.tokenId == TokenID.DotDotDot))) {\n // arg list\n variableArgList = this.parseFormalParameterList(errorRecoverySet, args, false, requiresSignature, indexer, isGetter, isSetter, isLambda, lambdaArgContext ? lambdaArgContext.preProcessedLambdaArgs : null, expectClosingRParen);\n }\n this.state = ParseState.FncDeclArgs;\n var returnType: AST = null;\n if (this.currentToken.tokenId == TokenID.Colon) {\n this.currentToken = this.scanner.scan();\n if (hasFlag(modifiers, Modifiers.Setter)) {\n this.reportParseError(\"Property setters may not declare a return type\");\n }\n returnType = this.parseTypeReference(errorRecoverySet, true);\n }\n\n if (indexer && args.members.length == 0) {\n this.reportParseError(\"Index signatures require a parameter type to be specified\");\n }\n this.state = ParseState.FncDeclReturnType;\n\n if (isLambda && this.currentToken.tokenId != TokenID.EqualsGreaterThan) {\n this.reportParseError(\"Expected '=>'\");\n }\n\n // REVIEW:\n // Currently, it's imperative that ambient functions *not* be marked as overloads. At some point, we may\n // want to unify the two concepts internally\n if (isDecl && !(this.parsingDeclareFile || markedAsAmbient) && (!isMethod || !(this.ambientModule || this.ambientClass || this.inInterfaceDecl)) && this.currentToken.tokenId == TokenID.Semicolon) {\n isOverload = true;\n isDecl = false;\n requiresSignature = true;\n }\n var svInFncDecl = this.inFncDecl;\n this.inFncDecl = true;\n var funcDecl: FuncDecl =\n this.parseFunctionStatements(\n errorRecoverySet | ErrorRecoverySet.RCurly,\n name, /*isConstructor:*/ false, isMethod, args, AllowedElements.None,\n minChar, requiresSignature, Modifiers.None);\n\n this.inFncDecl = svInFncDecl;\n funcDecl.variableArgList = variableArgList;\n funcDecl.isOverload = isOverload;\n\n if (!requiresSignature) { // REVIEW: What's the point of this? Why not just use 'Signature' instead of 'Definition'?\n funcDecl.fncFlags |= FncFlags.Definition;\n }\n\n if (isStatic) {\n funcDecl.fncFlags |= FncFlags.Static;\n }\n\n if (requiresSignature) {\n funcDecl.fncFlags |= FncFlags.Signature;\n }\n if (indexer) {\n funcDecl.fncFlags |= FncFlags.IndexerMember;\n }\n funcDecl.returnTypeAnnotation = returnType;\n if (isMethod) {\n funcDecl.fncFlags |= FncFlags.Method;\n // all class property methods are currently exported\n funcDecl.fncFlags |= FncFlags.ClassPropertyMethodExported;\n }\n funcDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n funcDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n\n this.nestingLevel = prevNestingLevel;\n this.parsingClassConstructorDefinition = prevInConstr;\n funcDecl.preComments = preComments;\n return funcDecl;\n }\n\n private convertToTypeReference(ast: AST): TypeReference {\n var result: TypeReference;\n switch (ast.nodeType) {\n case NodeType.TypeRef:\n return <TypeReference>ast;\n case NodeType.Name:\n result = new TypeReference(ast, 0);\n result.minChar = ast.minChar;\n result.limChar = ast.limChar;\n return result;\n case NodeType.Index: {\n var expr = <BinaryExpression>ast;\n result = this.convertToTypeReference(expr.operand1);\n if (result) {\n result.arrayCount++;\n result.minChar = expr.minChar;\n result.limChar = expr.limChar;\n return result;\n }\n else {\n var etr = <TypeReference>new AST(NodeType.Error);\n return etr;\n }\n }\n }\n return null;\n }\n\n private parseArgList(errorRecoverySet: ErrorRecoverySet): ASTList {\n var args: ASTList = new ASTList();\n args.minChar = this.scanner.startPos;\n\n // skip left paren\n this.currentToken = this.scanner.scan();\n\n if (this.currentToken.tokenId !== TokenID.CloseParen) {\n while (true) {\n if (args.members.length > 0xffff) {\n this.reportParseError(\"max number of args exceeded\");\n break;\n }\n\n var arg = this.parseExpr(\n ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, \n /*allowIn:*/ true,\n TypeContext.NoTypes);\n\n args.append(arg);\n if (this.currentToken.tokenId != TokenID.Comma) {\n break;\n }\n\n this.currentToken = this.scanner.scan();\n }\n }\n\n args.limChar = this.scanner.pos;\n return args;\n }\n\n private parseBaseList(extendsList: ASTList,\n implementsList: ASTList,\n errorRecoverySet: ErrorRecoverySet,\n isClass: bool): void {\n var keyword = true;\n var currentList = extendsList;\n for (; ;) {\n if (keyword) {\n if (this.currentToken.tokenId === TokenID.Implements) {\n currentList = implementsList;\n }\n else if (this.currentToken.tokenId == TokenID.Extends && !this.requiresExtendsBlock) {\n this.requiresExtendsBlock = isClass;\n }\n this.currentToken = this.scanner.scan();\n keyword = false;\n }\n var baseName: Identifier = null;\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n var minChar = this.scanner.startPos;\n baseName = Identifier.fromToken(this.currentToken);\n baseName.minChar = minChar;\n baseName.limChar = this.scanner.pos;\n baseName = <Identifier>this.parseNamedType(errorRecoverySet | ErrorRecoverySet.LCurly,\n minChar, baseName, false);\n }\n else {\n this.reportParseError(\"Expected base name\");\n if (this.errorRecovery) {\n baseName = new MissingIdentifier();\n baseName.minChar = this.scanner.pos;\n baseName.limChar = this.scanner.pos;\n baseName.flags |= ASTFlags.Error;\n }\n }\n if (this.currentToken.tokenId == TokenID.OpenParen) {\n if (isClass) {\n this.reportParseError(\"Base classes may only be initialized via a 'super' call within the constructor body\");\n }\n else {\n this.reportParseError(\"Interfaces may not be extended with a call expression\");\n }\n }\n else {\n currentList.append(baseName);\n }\n\n if (isClass && currentList == extendsList && extendsList.members.length > 1) {\n this.reportParseError(\"A class may only extend one other class\");\n }\n\n if (this.currentToken.tokenId == TokenID.Comma) {\n this.currentToken = this.scanner.scan();\n continue;\n }\n\n else if ((this.currentToken.tokenId == TokenID.Extends) ||\n (this.currentToken.tokenId == TokenID.Implements)) {\n\n if (this.currentToken.tokenId == TokenID.Extends && !this.requiresExtendsBlock) {\n this.requiresExtendsBlock = isClass;\n }\n\n currentList = extendsList;\n keyword = true;\n continue;\n }\n\n break;\n }\n }\n\n private parseClassDecl(errorRecoverySet: ErrorRecoverySet, minChar: number, modifiers: Modifiers): ClassDeclaration {\n var leftCurlyCount = this.scanner.leftCurlyCount;\n var rightCurlyCount = this.scanner.rightCurlyCount;\n\n if ((modifiers & Modifiers.Readonly) != Modifiers.None) {\n this.reportParseError(\"const modifier is implicit for class\");\n }\n\n // mark the class as ambient, as necessary\n if (this.parsingDeclareFile || this.ambientModule) {\n modifiers |= Modifiers.Ambient;\n modifiers |= Modifiers.Exported;\n }\n var classIsMarkedAsAmbient = this.parsingDeclareFile || (modifiers & Modifiers.Ambient) != Modifiers.None;\n var svAmbientClass = this.ambientClass;\n this.ambientClass = classIsMarkedAsAmbient;\n\n // grab the class's name\n this.currentToken = this.scanner.scan();\n var name: Identifier = null;\n if ((this.currentToken.tokenId == TokenID.Identifier) || (!isPrimitiveTypeToken(this.currentToken) && convertTokToID(this.currentToken, this.strictMode)) ) {\n name = Identifier.fromToken(this.currentToken);\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n else {\n this.reportParseError(\"class missing name\");\n if (this.errorRecovery) {\n name = new MissingIdentifier();\n name.minChar = this.scanner.pos;\n name.limChar = this.scanner.pos;\n name.flags |= ASTFlags.Error;\n }\n }\n\n var extendsList: ASTList = null;\n var implementsList: ASTList = null;\n var requiresSignature = false;\n\n if ((this.currentToken.tokenId == TokenID.Extends) ||\n (this.currentToken.tokenId == TokenID.Implements)) {\n extendsList = new ASTList();\n implementsList = new ASTList();\n this.parseBaseList(extendsList, implementsList, errorRecoverySet, /*isClass:*/ true);\n }\n\n // REVIEW: Note that we don't set this as the current class decl\n var classDecl = new ClassDeclaration(name, new ASTList(), extendsList, implementsList);\n\n this.currentClassDefinition = classDecl;\n\n // parse the classes members\n this.parseClassElements(classDecl, errorRecoverySet, modifiers);\n\n if (this.ambientModule || this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Exported)) {\n classDecl.varFlags |= VarFlags.Exported;\n }\n\n if (this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n classDecl.varFlags |= VarFlags.Ambient;\n }\n\n classDecl.varFlags |= VarFlags.Class;\n\n this.ambientClass = svAmbientClass;\n classDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n classDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n return classDecl;\n }\n\n private parseClassElements(classDecl: ClassDeclaration, errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers) {\n var modifiers = parentModifiers;\n var resetModifiers = false;\n\n var membersMinChar = this.scanner.startPos;\n this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet);\n\n this.nestingLevel++;\n\n var currentMemberMinChar = this.scanner.startPos;\n var wasGetOrSetId = false;\n\n while (!(this.currentToken.tokenId == TokenID.CloseBrace || this.currentToken.tokenId == TokenID.EndOfFile)) {\n var scanNext = true;\n var publicOrPrivateFlags = Modifiers.Public | Modifiers.Private;\n\n // modifiers\n if (this.currentToken.tokenId == TokenID.Get) {\n if (modifiers & Modifiers.Getter) {\n this.reportParseError(\"Duplicate 'get' declaration in class body\");\n }\n if (modifiers & Modifiers.Setter) {\n this.reportParseError(\"Getter already marked as a setter\");\n }\n modifiers |= Modifiers.Getter;\n }\n else if (this.currentToken.tokenId == TokenID.Set) {\n if (modifiers & Modifiers.Setter) {\n this.reportParseError(\"Duplicate 'set' declaration in class body\");\n }\n if (modifiers & Modifiers.Getter) {\n this.reportParseError(\"Setter already marked as a getter\");\n }\n modifiers |= Modifiers.Setter;\n\n }\n else if (this.currentToken.tokenId == TokenID.Private) {\n if (modifiers & publicOrPrivateFlags) {\n this.reportParseError(\"Multiple modifiers may not be applied to class members\");\n }\n modifiers |= Modifiers.Private;\n }\n else if (this.currentToken.tokenId == TokenID.Public) {\n if (modifiers & publicOrPrivateFlags) {\n this.reportParseError(\"Multiple modifiers may not be applied to class members\");\n }\n modifiers |= Modifiers.Public;\n }\n else if (this.currentToken.tokenId == TokenID.Static) {\n if (modifiers & Modifiers.Static) { // only check for double instances of static\n this.reportParseError(\"Multiple modifiers may not be applied to class members\");\n }\n modifiers |= Modifiers.Static;\n } // constructors\n else if (this.currentToken.tokenId == TokenID.Constructor) {\n\n if (modifiers != parentModifiers) {\n this.reportParseError(\"Constructors may not have modifiers\");\n }\n\n this.parseClassConstructorDeclaration(currentMemberMinChar, errorRecoverySet, modifiers);\n scanNext = false; // parsing functions advances the token for us\n resetModifiers = true;\n } // member declarations\n else if (wasGetOrSetId || this.currentToken.tokenId == TokenID.Identifier || convertTokToIDName(this.currentToken)) {\n\n var idText = wasGetOrSetId ? ((modifiers & Modifiers.Getter) ? \"get\" : \"set\") : this.currentToken.getText();\n var id = wasGetOrSetId ? new Identifier(idText) : Identifier.fromToken(this.currentToken);\n id.minChar = this.scanner.startPos;\n id.limChar = this.scanner.pos;\n\n // unset the get/set bit, if we're using it for an id\n if (wasGetOrSetId) {\n modifiers = modifiers ^ ((modifiers & Modifiers.Getter) ? Modifiers.Getter : Modifiers.Setter);\n wasGetOrSetId = false;\n }\n else {\n this.currentToken = this.scanner.scan();\n }\n\n if (this.currentToken.tokenId == TokenID.OpenParen) {\n this.parseClassMemberFunctionDeclaration(id, currentMemberMinChar, errorRecoverySet, modifiers);\n scanNext = false; // parsing functions advances the token for us\n }\n else {\n if (modifiers & Modifiers.Getter || modifiers & Modifiers.Setter) {\n this.reportParseError(\"Property accessors must be functions\");\n }\n\n var varDecl = this.parseClassMemberVariableDeclaration(id, currentMemberMinChar, false, errorRecoverySet, modifiers);\n\n if (varDecl.init && varDecl.init.nodeType == NodeType.FuncDecl) {\n if (this.currentToken.tokenId == TokenID.CloseBrace) {\n scanNext = false;\n }\n }\n else if (varDecl.init && varDecl.init.nodeType == NodeType.ObjectLit && this.currentToken.tokenId != TokenID.Semicolon) {\n scanNext = false;\n varDecl.init.flags |= ASTFlags.AutomaticSemicolon;\n }\n else if (this.currentToken.tokenId != TokenID.Semicolon) {\n this.reportParseError(\"Expected ';'\");\n scanNext = false;\n }\n }\n\n resetModifiers = true;\n } // catch errant uses of 'super'\n else if (this.currentToken.tokenId == TokenID.Super) {\n this.reportParseError(\"Base class initializers must be the first statement in a class definition\");\n }\n else if (!wasGetOrSetId && ((modifiers & Modifiers.Getter) || (modifiers & Modifiers.Setter)) &&\n ((this.currentToken.tokenId == TokenID.OpenParen) || (this.currentToken.tokenId == TokenID.Equals) ||\n (this.currentToken.tokenId == TokenID.Colon) || (this.currentToken.tokenId == TokenID.Semicolon))) {\n // catch a 'get' or 'set' used as an identifier\n wasGetOrSetId = true;\n scanNext = false;\n\n } // mark anything else as an error\n else if (this.currentToken.tokenId != TokenID.Semicolon) { // jettison semicolons\n this.reportParseError(\"Unexpected '\" + this.currentToken.getText() + \"' in class definition\");\n resetModifiers = true;\n }\n\n if (scanNext) {\n this.currentToken = this.scanner.scan();\n }\n\n if (resetModifiers) {\n modifiers = parentModifiers;\n currentMemberMinChar = this.scanner.startPos;\n resetModifiers = false;\n }\n }\n\n var membersLimChar = this.scanner.pos;\n if (this.currentToken.tokenId == TokenID.CloseBrace) {\n classDecl.endingToken = new ASTSpan();\n classDecl.endingToken.minChar = this.scanner.startPos;\n classDecl.endingToken.limChar = this.scanner.pos;\n\n // for a class with an empty body, consume any 'dangling' inner comments\n if (!this.currentClassDefinition.members.members.length) {\n this.currentClassDefinition.preComments = this.parseComments();\n }\n\n this.currentToken = this.scanner.scan();\n }\n\n this.nestingLevel--;\n\n this.currentClassDefinition.members.minChar = membersMinChar;\n this.currentClassDefinition.members.limChar = membersLimChar;\n this.currentClassDefinition.limChar = membersLimChar;\n this.currentClassDefinition = null;\n }\n\n private parseClassConstructorDeclaration(minChar: number, errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers) {\n this.parsingClassConstructorDefinition = true;\n\n var isAmbient = this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient);\n\n var args: ASTList = new ASTList();\n var variableArgList = false;\n var preComments = this.parseComments();\n\n this.currentToken = this.scanner.scan(); // scan past the 'constructor' token\n\n if (this.currentToken.tokenId == TokenID.OpenParen) {\n variableArgList = this.parseFormalParameterList(errorRecoverySet, args, true, isAmbient, false, false, false, false, null, true);\n if (args.members.length > 0) {\n var lastArg = args.members[args.members.length - 1];\n }\n }\n\n var requiresSignature = isAmbient || this.currentToken.tokenId == TokenID.Semicolon;\n\n\n if (requiresSignature) {\n for (var i = 0; i < args.members.length; i++) {\n var arg = <ArgDecl> args.members[i];\n if (hasFlag(arg.varFlags, VarFlags.Property)) {\n this.reportParseError(\"Overload or ambient signatures may not specify parameter properties\", arg.minChar, arg.limChar);\n }\n }\n }\n\n if (!requiresSignature) {\n this.currentClassDefinition.constructorNestingLevel = this.nestingLevel + 1;\n }\n\n var constructorFuncDecl = this.parseFunctionStatements(\n errorRecoverySet | ErrorRecoverySet.RCurly, this.currentClassDefinition.name, \n /*isConstructor:*/ true, /*isMethod:*/ false, args, AllowedElements.Properties, \n minChar, requiresSignature, modifiers);\n\n constructorFuncDecl.preComments = preComments;\n\n if (requiresSignature && !isAmbient) {\n constructorFuncDecl.isOverload = true;\n }\n\n constructorFuncDecl.variableArgList = variableArgList;\n this.currentClassDecl = null;\n constructorFuncDecl.returnTypeAnnotation = this.convertToTypeReference(this.currentClassDefinition.name);\n constructorFuncDecl.classDecl = this.currentClassDefinition;\n\n if (isAmbient) {\n constructorFuncDecl.fncFlags |= FncFlags.Ambient;\n }\n\n if (requiresSignature) {\n constructorFuncDecl.fncFlags |= FncFlags.Signature;\n }\n\n if (this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n constructorFuncDecl.fncFlags |= FncFlags.Exported;\n }\n\n\n if (this.currentClassDefinition.constructorDecl) {\n if (!isAmbient && !this.currentClassDefinition.constructorDecl.isSignature() && !constructorFuncDecl.isSignature()) {\n this.reportParseError(\"Duplicate constructor definition\");\n }\n }\n\n if (isAmbient || !constructorFuncDecl.isSignature()) {\n this.currentClassDefinition.constructorDecl = constructorFuncDecl;\n }\n\n // REVIEW: Should we have a separate flag for class constructors? (Constructors are not methods)\n constructorFuncDecl.fncFlags |= FncFlags.ClassMethod;\n\n this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = constructorFuncDecl;\n\n this.parsingClassConstructorDefinition = false;\n\n return constructorFuncDecl;\n }\n\n private parseClassMemberVariableDeclaration(text: Identifier, minChar: number, isDeclaredInConstructor: bool, errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers) {\n\n var varDecl = new VarDecl(text, this.nestingLevel);\n varDecl.minChar = minChar;\n var isStatic = false;\n varDecl.preComments = this.parseComments();\n\n if (this.currentToken.tokenId == TokenID.Colon) {\n this.currentToken = this.scanner.scan();\n varDecl.typeExpr =\n this.parseTypeReference(errorRecoverySet | ErrorRecoverySet.Asg | ErrorRecoverySet.Comma, false);\n if (varDecl.typeExpr && varDecl.typeExpr.nodeType == NodeType.TypeRef) {\n var typeExpr = (<TypeReference>varDecl.typeExpr);\n if (typeExpr.term && typeExpr.term.nodeType == NodeType.FuncDecl) {\n typeExpr.term.preComments = varDecl.preComments;\n }\n }\n }\n\n if (this.currentToken.tokenId == TokenID.Equals) {\n if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n this.reportParseError(\"context does not permit variable initializer\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n varDecl.flags |= ASTFlags.Error;\n varDecl.limChar = this.scanner.lastTokenLimChar();\n return varDecl;\n }\n }\n\n // TODO: note assignment for language service\n this.currentToken = this.scanner.scan();\n\n varDecl.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n\n varDecl.limChar = varDecl.init.limChar;\n\n // member initializers on instance properties require that super be invoked as the first call within the constructor\n if (!(modifiers & Modifiers.Static)) {\n this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n }\n }\n else {\n varDecl.limChar = this.scanner.pos;\n }\n\n if (modifiers & Modifiers.Static) {\n varDecl.varFlags |= VarFlags.Static;\n isStatic = true;\n }\n\n if ((modifiers & Modifiers.Private) != Modifiers.None) {\n varDecl.varFlags |= VarFlags.Private;\n }\n else {\n varDecl.varFlags |= VarFlags.Public;\n }\n\n varDecl.varFlags |= VarFlags.Property;\n\n if (isDeclaredInConstructor) {\n varDecl.varFlags |= VarFlags.ClassConstructorProperty;\n }\n\n if (!isDeclaredInConstructor && !isStatic) {\n varDecl.varFlags |= VarFlags.ClassBodyProperty;\n }\n\n this.currentClassDefinition.knownMemberNames[text.actualText] = true;\n\n if (!isDeclaredInConstructor) {\n this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = varDecl;\n }\n\n varDecl.postComments = this.parseComments();\n return varDecl;\n }\n\n private parseClassMemberFunctionDeclaration(methodName: Identifier, minChar: number, errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers) {\n var wasAccessorID = this.prevIDTok != null;\n var isAccessor = hasFlag(modifiers, Modifiers.Getter) || hasFlag(modifiers, Modifiers.Setter);\n var isStatic = hasFlag(modifiers, Modifiers.Static);\n\n var isAmbient = this.ambientModule || hasFlag(modifiers, Modifiers.Ambient);\n\n errorRecoverySet |= ErrorRecoverySet.RParen;\n\n if (isAccessor && (modifiers & Modifiers.Ambient)) {\n this.reportParseError(\"Property accessors may not be declared in ambient classes\");\n }\n\n // REVIEW: Why bother passing in isAmbient for both requiresSignature and isAmbient? Shouldn't just saying its ambient suffice?\n var ast: AST = this.parseFncDecl(errorRecoverySet, true, isAmbient, true, methodName, false, isStatic, isAmbient, modifiers, null, true);\n if (ast.nodeType == NodeType.Error) {\n return ast;\n }\n\n var funcDecl = <FuncDecl>ast;\n\n funcDecl.minChar = minChar;\n if (funcDecl.bod !== null)\n funcDecl.limChar = funcDecl.bod.limChar;\n\n if (modifiers & Modifiers.Private) {\n funcDecl.fncFlags |= FncFlags.Private;\n }\n else {\n funcDecl.fncFlags |= FncFlags.Public;\n }\n\n if (isStatic) {\n funcDecl.fncFlags |= FncFlags.Static;\n }\n\n if (isAccessor) {\n // REVIEW: verify return-type annotations and arguments\n if (hasFlag(modifiers, Modifiers.Getter)) {\n funcDecl.fncFlags |= FncFlags.GetAccessor;\n funcDecl.hint = \"get\" + funcDecl.name.actualText;\n }\n else {\n funcDecl.fncFlags |= FncFlags.SetAccessor;\n funcDecl.hint = \"set\" + funcDecl.name.actualText;\n }\n funcDecl.fncFlags |= FncFlags.IsFunctionExpression;\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\", funcDecl.minChar, funcDecl.limChar);\n }\n }\n\n funcDecl.fncFlags |= FncFlags.ClassMethod;\n\n this.currentClassDefinition.knownMemberNames[methodName.actualText] = true;\n\n this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = funcDecl;\n\n return funcDecl;\n }\n\n private parseTypeMember(errorRecoverySet: ErrorRecoverySet): AST {\n var minChar = this.scanner.startPos;\n\n var propertyDecl = this.parsePropertyDeclaration(\n errorRecoverySet, Modifiers.Public, /*requireSignature:*/ true, /*isStatic:*/ false);\n\n if (propertyDecl) {\n propertyDecl.minChar = minChar;\n\n if (propertyDecl.nodeType == NodeType.VarDecl) {\n this.checkCurrentToken(TokenID.Semicolon, errorRecoverySet);\n }\n }\n\n return propertyDecl;\n }\n\n private parseTypeMemberList(errorRecoverySet: ErrorRecoverySet, members: ASTList) {\n errorRecoverySet |= ErrorRecoverySet.TypeScriptS;\n while (true) {\n switch (this.currentToken.tokenId) {\n case TokenID.CloseBrace:\n case TokenID.EndOfFile:\n members.limChar = this.scanner.pos;\n return;\n }\n\n // REVIEW: This code looks suspect. If parseTypeMember returns null, then \n // won't we just infinite loop?\n var element = this.parseTypeMember(errorRecoverySet);\n if (element) {\n members.append(element);\n }\n }\n }\n\n private parseInterfaceDecl(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers): InterfaceDeclaration {\n var leftCurlyCount = this.scanner.leftCurlyCount;\n var rightCurlyCount = this.scanner.rightCurlyCount;\n\n this.currentToken = this.scanner.scan();\n var minChar = this.scanner.pos;\n var name: Identifier = null;\n if ((this.currentToken.tokenId == TokenID.Identifier) || (!isPrimitiveTypeToken(this.currentToken) && convertTokToID(this.currentToken, this.strictMode))) {\n name = Identifier.fromToken(this.currentToken);\n name.minChar = this.scanner.startPos;\n name.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n else {\n this.reportParseError(\"interface missing name\");\n if (this.errorRecovery) {\n name = new MissingIdentifier();\n name.minChar = this.scanner.pos;\n name.limChar = this.scanner.pos;\n name.flags |= ASTFlags.Error;\n }\n }\n\n var extendsList: ASTList = null;\n var implementsList: ASTList = null;\n if (this.currentToken.tokenId === TokenID.Extends || this.currentToken.tokenId === TokenID.Implements) {\n if (this.currentToken.tokenId === TokenID.Implements) {\n this.reportParseError(\"Expected 'extends'\");\n }\n\n extendsList = new ASTList();\n implementsList = new ASTList();\n extendsList.minChar = this.scanner.startPos;\n this.parseBaseList(extendsList, implementsList, errorRecoverySet, /*isClass:*/ false);\n }\n\n var membersMinChar = this.scanner.startPos;\n this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.TypeScriptS);\n var members = new ASTList();\n members.minChar = membersMinChar;\n var prevInInterfaceDecl = this.inInterfaceDecl;\n this.inInterfaceDecl = true;\n this.parseTypeMemberList(errorRecoverySet | ErrorRecoverySet.RCurly, members);\n this.inInterfaceDecl = prevInInterfaceDecl;\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n // REVIEW: According to the grammar, an interface declaration should actually just\n // have an 'ObjectType' and not a list of members. We may want to consider making that\n // change. Note: it would mean breaking aparat TypeDecl into InterfaceDeclaration and \n // ClassDeclaration.\n var interfaceDecl = new InterfaceDeclaration(name, members, extendsList, null);\n if (hasFlag(modifiers, Modifiers.Private)) {\n interfaceDecl.varFlags |= VarFlags.Private;\n }\n if (hasFlag(modifiers, Modifiers.Public)) {\n interfaceDecl.varFlags |= VarFlags.Public;\n }\n if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n interfaceDecl.varFlags |= VarFlags.Exported;\n }\n\n interfaceDecl.limChar = members.limChar;\n interfaceDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n interfaceDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n return interfaceDecl;\n }\n\n private makeVarDecl(id: Identifier, nest: number): VarDecl {\n var varDecl = new VarDecl(id, nest);\n var currentVarList = this.topVarList();\n if (currentVarList) {\n currentVarList.append(varDecl);\n }\n return varDecl;\n }\n\n private parsePropertyDeclaration(\n errorRecoverySet: ErrorRecoverySet,\n modifiers: Modifiers,\n requireSignature: bool,\n isStatic: bool): AST {\n\n var text: Identifier = null;\n var minChar = this.scanner.startPos;\n var nameLimChar = minChar;\n var isNew = false;\n var isIndexer = false;\n var wasAccessorID = this.prevIDTok != null;\n var isAccessor = hasFlag(modifiers, Modifiers.Getter) || hasFlag(modifiers, Modifiers.Setter);\n\n if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n requireSignature = true;\n }\n\n if (this.currentToken.tokenId == TokenID.OpenParen && !wasAccessorID) {\n if (!requireSignature && !isStatic) {\n this.reportParseError(\"Expected identifier in property declaration\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n //REVIEW: Use something else than \"Identifier\"?\n text = new MissingIdentifier();\n }\n }\n }\n else if (this.currentToken.tokenId == TokenID.New) {\n if (requireSignature) {\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.OpenParen) {\n isNew = true;\n }\n }\n\n if (!isNew) {\n // is identifier\n if (!requireSignature) {\n this.currentToken = this.scanner.scan();\n }\n text = new Identifier(\"new\");\n text.minChar = this.scanner.pos - 3;\n text.limChar = this.scanner.pos;\n nameLimChar = this.scanner.pos;\n }\n }\n else if ((this.currentToken.tokenId == TokenID.OpenBracket) && requireSignature) {\n // indexer signature\n isIndexer = true;\n //REVIEW: Should we use a special \"compiler reserved\" identifier node?\n text = new Identifier(\"__item\");\n }\n else if ((this.currentToken.tokenId != TokenID.Identifier) && (!convertTokToIDName(this.currentToken)) && !wasAccessorID) {\n this.reportParseError(\"Expected identifier in property declaration\");\n if (this.errorRecovery) {\n var eminChar = this.scanner.startPos;\n var curpos = this.scanner.pos;\n this.skip(errorRecoverySet & (~ErrorRecoverySet.Comma));\n if (this.scanner.pos == curpos) {\n // ensure progress\n this.currentToken = this.scanner.scan();\n }\n\n var epd = new VarDecl(new MissingIdentifier(), this.nestingLevel);\n epd.flags |= ASTFlags.Error;\n epd.minChar = eminChar;\n epd.limChar = this.scanner.lastTokenLimChar();\n return epd;\n }\n }\n else {\n if (wasAccessorID) {\n text = Identifier.fromToken(this.prevIDTok);\n text.minChar = this.scanner.lastTokenLimChar() - 3;\n text.limChar = this.scanner.lastTokenLimChar();\n nameLimChar = text.limChar;\n\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n\n // this block guards against 'get' and 'set' tokens that\n // were coerced into identifiers\n if (this.currentToken.getText() == text.actualText && this.currentToken != this.prevIDTok) {\n this.currentToken = this.scanner.scan();\n } // Otherwise, don't update the token - we're already at '('\n\n // reset the previous ID Token\n this.prevIDTok = null;\n }\n else {\n text = Identifier.fromToken(this.currentToken);\n text.minChar = this.scanner.startPos;\n text.limChar = this.scanner.pos;\n nameLimChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n }\n\n if (this.currentToken.tokenId == TokenID.Question) {\n if (this.inInterfaceDecl && text) {\n text.flags |= ASTFlags.OptionalName;\n }\n else {\n this.reportParseError(\"Optional properties may only be declared on interface or object types\");\n }\n this.currentToken = this.scanner.scan();\n }\n\n if ((this.currentToken.tokenId == TokenID.OpenParen) ||\n (isIndexer && (this.currentToken.tokenId == TokenID.OpenBracket))) {\n var ers = errorRecoverySet | ErrorRecoverySet.RParen;\n if (isIndexer) {\n ers = errorRecoverySet | ErrorRecoverySet.RBrack;\n }\n var ast = this.parseFncDecl(ers, true, requireSignature,\n !this.inFncDecl, text, isIndexer, isStatic, (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)), modifiers, null, true);\n var funcDecl: FuncDecl;\n if (ast.nodeType == NodeType.Error) {\n return ast;\n }\n else {\n funcDecl = <FuncDecl>ast;\n }\n if (funcDecl.name) {\n funcDecl.name.minChar = minChar;\n funcDecl.name.limChar = nameLimChar;\n }\n if ((modifiers & Modifiers.Public) != Modifiers.None) {\n funcDecl.fncFlags |= FncFlags.Public;\n }\n if ((modifiers & Modifiers.Private) != Modifiers.None) {\n funcDecl.fncFlags |= FncFlags.Private;\n }\n if (isStatic) {\n funcDecl.fncFlags |= FncFlags.Static;\n }\n if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n funcDecl.fncFlags |= FncFlags.Ambient;\n }\n if (isAccessor) {\n // REVIEW: verify return-type annotations and arguments\n if (hasFlag(modifiers, Modifiers.Getter)) {\n funcDecl.fncFlags |= FncFlags.GetAccessor;\n funcDecl.hint = \"get\" + funcDecl.name.actualText;\n }\n else {\n funcDecl.fncFlags |= FncFlags.SetAccessor;\n funcDecl.hint = \"set\" + funcDecl.name.actualText;\n }\n funcDecl.fncFlags |= FncFlags.IsFunctionExpression;\n\n if (modifiers & Modifiers.Ambient) {\n this.reportParseError(\"Property accessors may not be declared in ambient types\");\n }\n }\n\n if (text == null) {\n if (isNew) {\n funcDecl.fncFlags |= FncFlags.ConstructMember;\n funcDecl.hint = \"_construct\";\n funcDecl.classDecl = this.currentClassDecl;\n }\n else {\n funcDecl.hint = \"_call\";\n funcDecl.fncFlags |= FncFlags.CallMember;\n }\n }\n return funcDecl;\n }\n else {\n var varDecl = new VarDecl(text, this.nestingLevel);\n varDecl.preComments = this.parseComments();\n varDecl.minChar = minChar;\n if (this.currentToken.tokenId == TokenID.Colon) {\n this.currentToken = this.scanner.scan();\n varDecl.typeExpr =\n this.parseTypeReference(errorRecoverySet | ErrorRecoverySet.Asg |\n ErrorRecoverySet.Comma, false);\n if (varDecl.typeExpr && varDecl.typeExpr.nodeType == NodeType.TypeRef) {\n var typeExpr = (<TypeReference>varDecl.typeExpr);\n if (typeExpr.term && typeExpr.term.nodeType == NodeType.FuncDecl) {\n typeExpr.term.preComments = varDecl.preComments;\n }\n }\n }\n if (this.currentToken.tokenId == TokenID.Equals) {\n if (requireSignature) {\n this.reportParseError(\"context does not permit variable initializer\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n varDecl.flags |= ASTFlags.Error;\n varDecl.limChar = this.scanner.lastTokenLimChar();\n return varDecl;\n }\n }\n // TODO: note assignment for language service\n this.currentToken = this.scanner.scan();\n varDecl.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n varDecl.limChar = varDecl.init.limChar;\n if (varDecl.init.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>varDecl.init;\n funcDecl.hint = varDecl.id.text;\n funcDecl.boundToProperty = varDecl;\n }\n else if (isAccessor) {\n this.reportParseError(\"Accessors may only be functions\");\n }\n }\n else {\n varDecl.limChar = this.scanner.pos;\n }\n if ((modifiers & Modifiers.Readonly) != Modifiers.None) {\n varDecl.varFlags |= VarFlags.Readonly;\n }\n if (isStatic) {\n varDecl.varFlags |= VarFlags.Static;\n }\n if ((modifiers & Modifiers.Public) != Modifiers.None) {\n varDecl.varFlags |= VarFlags.Public;\n }\n if ((modifiers & Modifiers.Private) != Modifiers.None) {\n varDecl.varFlags |= VarFlags.Private;\n }\n varDecl.varFlags |= VarFlags.Property;\n return varDecl;\n }\n }\n\n private parseVariableDeclaration(\n errorRecoverySet: ErrorRecoverySet,\n modifiers: Modifiers,\n allowIn: bool,\n isStatic: bool): AST {\n\n var isConst = hasFlag(modifiers, Modifiers.Readonly);\n var minChar = this.scanner.startPos;\n var varDecl: VarDecl = null;\n var declList: ASTList = null;\n var multivar = false;\n\n this.currentToken = this.scanner.scan();\n var varDeclPreComments = this.parseComments();\n\n while (true) {\n if ((this.currentToken.tokenId != TokenID.Identifier) && (!convertTokToID(this.currentToken, this.strictMode))) {\n this.reportParseError(\"Expected identifier in variable declaration\");\n\n if (this.errorRecovery) {\n varDecl = new VarDecl(new MissingIdentifier(), this.nestingLevel);\n varDecl.minChar = minChar;\n this.skip(errorRecoverySet);\n varDecl.flags |= ASTFlags.Error;\n varDecl.limChar = this.scanner.lastTokenLimChar();\n return varDecl;\n }\n }\n\n var varDeclName = Identifier.fromToken(this.currentToken)\n if (this.strictMode && (varDeclName.text == \"eval\")) {\n this.reportParseError(\"'eval' may not name a variable in strict mode\");\n }\n\n varDecl = this.makeVarDecl(varDeclName, this.nestingLevel);\n varDecl.id.minChar = this.scanner.startPos;\n varDecl.id.limChar = this.scanner.pos;\n varDecl.preComments = varDeclPreComments;\n\n if (isStatic) {\n varDecl.varFlags |= VarFlags.Static;\n }\n if (hasFlag(modifiers, Modifiers.Readonly)) {\n varDecl.varFlags |= VarFlags.Readonly;\n }\n if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n varDecl.varFlags |= VarFlags.Ambient;\n }\n if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n varDecl.varFlags |= VarFlags.Exported;\n }\n varDecl.minChar = minChar;\n if (declList) {\n declList.append(varDecl);\n }\n\n // move past ID; with error recovery need a test \n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.Colon) {\n this.currentToken = this.scanner.scan();\n var prevInFncDecl = this.inFncDecl;\n this.inFncDecl = false;\n varDecl.typeExpr = this.parseTypeReference(\n errorRecoverySet | ErrorRecoverySet.Asg | ErrorRecoverySet.Comma, /*allowVoid:*/ false);\n this.inFncDecl = prevInFncDecl;\n }\n\n if (this.currentToken.tokenId == TokenID.Equals) {\n if (hasFlag(varDecl.varFlags, VarFlags.Ambient)) {\n this.reportParseError(\"Ambient variable can not have an initializer\");\n }\n // TODO: note assignment for language service\n this.currentToken = this.scanner.scan();\n varDecl.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, allowIn,\n TypeContext.NoTypes);\n varDecl.limChar = varDecl.init.limChar;\n if (varDecl.init.nodeType == NodeType.FuncDecl) {\n // TODO: use 'as' operator when can bootstrap\n var funcDecl = <FuncDecl>varDecl.init;\n funcDecl.hint = varDecl.id.actualText;\n }\n }\n else {\n if (isConst) {\n this.reportParseError(\"const declaration requires initializer\");\n }\n varDecl.limChar = this.scanner.pos;\n }\n varDecl.postComments = this.parseCommentsForLine(this.scanner.line);\n\n if (this.currentToken.tokenId != TokenID.Comma) {\n if (declList) {\n declList.limChar = varDecl.limChar;\n return declList;\n }\n else {\n return varDecl;\n }\n }\n\n if (!multivar) {\n declList = new ASTList();\n declList.minChar = varDecl.minChar;\n declList.append(varDecl);\n multivar = true;\n }\n\n this.currentToken = this.scanner.scan();\n minChar = this.scanner.startPos;\n }\n }\n\n private parseMemberList(errorRecoverySet: ErrorRecoverySet): ASTList {\n var elements = new ASTList();\n if (this.currentToken.tokenId == TokenID.CloseBrace) {\n return elements;\n }\n\n var idHint: string = null;\n var memberName: AST = null;\n var memberExpr: AST = null;\n var member: BinaryExpression = null;\n var minChar = this.scanner.startPos;\n var isSet = false;\n var skippedTokenForGetSetId = false;\n var getSetTok: Token = null;\n var getSetStartPos = 0;\n var getSetPos = 0;\n\n for (; ;) {\n var accessorPattern = false;\n if (this.currentToken.tokenId == TokenID.Get || this.currentToken.tokenId == TokenID.Set) {\n isSet = this.currentToken.tokenId == TokenID.Set;\n getSetTok = this.currentToken;\n getSetStartPos = this.scanner.startPos;\n getSetPos = this.scanner.pos;\n\n this.currentToken = this.scanner.scan();\n\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToIDName(this.currentToken)) {\n idHint = isSet ? \"set\" : \"get\";\n idHint = idHint + this.currentToken.getText();\n memberName = Identifier.fromToken(this.currentToken);\n memberName.minChar = this.scanner.startPos;\n accessorPattern = true;\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n }\n else if (this.currentToken.tokenId != TokenID.Colon) {\n this.reportParseError(\"Expected identifier, string or number as accessor name\");\n }\n else {\n skippedTokenForGetSetId = true;\n memberName = Identifier.fromToken(getSetTok);\n memberName.minChar = getSetStartPos;\n memberName.limChar = getSetPos;\n }\n }\n else if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToIDName(this.currentToken)) {\n idHint = this.currentToken.getText();\n memberName = Identifier.fromToken(this.currentToken);\n memberName.minChar = this.scanner.startPos;\n memberName.limChar = this.scanner.pos;\n }\n else if (this.currentToken.tokenId == TokenID.StringLiteral) {\n idHint = this.currentToken.getText();\n memberName = new StringLiteral(idHint);\n memberName.minChar = this.scanner.startPos;\n memberName.limChar = this.scanner.pos;\n }\n // TODO: allow reserved words\n else if (this.currentToken.tokenId == TokenID.NumberLiteral) {\n var ntok = <NumberLiteralToken>this.currentToken;\n idHint = ntok.value.toString();\n memberName = new StringLiteral(idHint);\n memberName.minChar = this.scanner.startPos;\n memberName.limChar = this.scanner.pos;\n }\n else {\n this.reportParseError(\"Expected identifier, string or number as member name\");\n if (this.errorRecovery) {\n memberName = new MissingIdentifier();\n memberName.minChar = this.scanner.startPos;\n memberName.flags |= ASTFlags.Error;\n this.skip(errorRecoverySet | ErrorRecoverySet.Comma);\n memberName.limChar = this.scanner.lastTokenLimChar();\n }\n }\n\n if (!skippedTokenForGetSetId) {\n this.currentToken = this.scanner.scan();\n }\n else {\n skippedTokenForGetSetId = false;\n }\n\n if (this.currentToken.tokenId == TokenID.Question) {\n memberName.flags |= ASTFlags.OptionalName;\n this.currentToken = this.scanner.scan();\n }\n\n if (accessorPattern) {\n var args = new ASTList();\n this.parseFormalParameterList(errorRecoverySet | ErrorRecoverySet.RParen,\n args, false, true, false, !isSet, isSet, false, null, true);\n\n var funcDecl: FuncDecl =\n this.parseFunctionStatements(errorRecoverySet | ErrorRecoverySet.RCurly,\n <Identifier>memberName, false, true, args,\n AllowedElements.None,\n this.scanner.startPos, false, Modifiers.None);\n\n if (isSet && funcDecl.returnTypeAnnotation) {\n this.reportParseError(\"Property setters may not declare a return type\");\n }\n\n funcDecl.fncFlags |= isSet ? FncFlags.SetAccessor : FncFlags.GetAccessor;\n funcDecl.fncFlags |= FncFlags.IsFunctionExpression;\n funcDecl.hint = idHint;\n memberExpr = funcDecl;\n member = new BinaryExpression(NodeType.Member, memberName, memberExpr);\n member.minChar = memberName.minChar;\n if (memberExpr.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>memberExpr;\n funcDecl.hint = idHint;\n }\n }\n else if (this.currentToken.tokenId == TokenID.Colon) {\n this.currentToken = this.scanner.scan();\n memberExpr = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n // If the memberExpr is a type reference, we can be certain that it was an\n // array type declaraion that lacked a \"new\". We can realistically only\n // expect call and name ASTs to be the result of this call to parseExpr.\n // If it's a constructor without a \"new\", we'll flag it as an invalid\n // call site later on.\n if (memberExpr.nodeType == NodeType.TypeRef) {\n this.reportParseError(\"Expected 'new' on array declaration in member definition\")\n }\n member = new BinaryExpression(NodeType.Member, memberName, memberExpr);\n member.minChar = memberName.minChar;\n if (memberExpr.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>memberExpr;\n funcDecl.hint = idHint;\n }\n }\n else {\n this.reportParseError(\"Expected ':' in member definition\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n elements.flags |= ASTFlags.Error;\n elements.minChar = minChar;\n elements.limChar = this.scanner.lastTokenLimChar();\n return elements;\n }\n }\n idHint = null;\n elements.append(member);\n member.limChar = this.scanner.lastTokenLimChar();\n if (this.currentToken.tokenId != TokenID.Comma) {\n break;\n }\n else {\n // munch comma\n this.currentToken = this.scanner.scan();\n }\n\n // trailing comma allowed\n if (this.currentToken.tokenId == TokenID.CloseBrace) {\n break;\n }\n }\n\n if (member) {\n elements.limChar = member.limChar;\n }\n elements.minChar = minChar;\n return elements;\n }\n\n private parseArrayList(errorRecoverySet: ErrorRecoverySet): ASTList {\n var elements: ASTList = null;\n if (this.currentToken.tokenId == TokenID.CloseBracket) {\n return elements;\n }\n else {\n elements = new ASTList();\n elements.minChar = this.scanner.startPos;\n }\n\n var arg: AST;\n\n for (; ;) {\n if ((this.currentToken.tokenId == TokenID.Comma) ||\n (this.currentToken.tokenId == TokenID.CloseBracket)) {\n arg = new AST(NodeType.EmptyExpr);\n }\n else {\n arg = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n }\n elements.append(arg);\n if (this.currentToken.tokenId != TokenID.Comma) {\n break;\n }\n this.currentToken = this.scanner.scan();\n }\n elements.limChar = this.scanner.lastTokenLimChar();\n return elements;\n }\n\n private parseArrayLiteral(errorRecoverySet: ErrorRecoverySet): UnaryExpression {\n var arrayLiteral: UnaryExpression = null;\n arrayLiteral = new UnaryExpression(NodeType.ArrayLit,\n this.parseArrayList(errorRecoverySet));\n return arrayLiteral;\n }\n\n private parseTerm(errorRecoverySet: ErrorRecoverySet, allowCall: bool, typeContext: TypeContext, inCast: bool): AST {\n var ast: AST = null;\n var sawId = false;\n var inNew = false;\n var minChar = this.scanner.startPos;\n var limChar = this.scanner.pos;\n var parseAsLambda = false;\n var expectlambdaRParen = false;\n\n // keywords first\n switch (this.currentToken.tokenId) {\n case TokenID.Number:\n case TokenID.Bool:\n case TokenID.Any:\n case TokenID.String:\n var tid = new Identifier(tokenTable[this.currentToken.tokenId].text);\n if (hasFlag(typeContext, TypeContext.Primitive)) {\n ast = new TypeReference(tid, 0);\n sawId = true;\n }\n else {\n ast = tid;\n sawId = true;\n }\n ast.minChar = minChar;\n this.currentToken = this.scanner.scan();\n limChar = this.scanner.lastTokenLimChar();\n break;\n case TokenID.This:\n ast = new AST(NodeType.This);\n ast.minChar = minChar;\n this.currentToken = this.scanner.scan();\n limChar = this.scanner.lastTokenLimChar();\n break;\n case TokenID.Super:\n ast = new AST(NodeType.Super);\n ast.minChar = minChar;\n this.currentToken = this.scanner.scan();\n limChar = this.scanner.lastTokenLimChar();\n break;\n case TokenID.True:\n ast = new AST(NodeType.True);\n this.currentToken = this.scanner.scan();\n ast.minChar = minChar;\n break;\n case TokenID.False:\n ast = new AST(NodeType.False);\n this.currentToken = this.scanner.scan();\n ast.minChar = minChar;\n break;\n case TokenID.Null:\n ast = new AST(NodeType.Null);\n this.currentToken = this.scanner.scan();\n ast.minChar = minChar;\n break;\n case TokenID.New:\n minChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n var target = this.parseTerm(errorRecoverySet, false, TypeContext.AllSimpleTypes, inCast);\n\n if (target.nodeType == NodeType.Error || (target.nodeType == NodeType.Index && (<BinaryExpression>target).operand1.nodeType == NodeType.TypeRef)) {\n this.reportParseError(\"Cannot invoke 'new' on this expression\");\n } else {\n ast = new CallExpression(NodeType.New, target, null);\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n inNew = true;\n }\n break;\n case TokenID.Function:\n minChar = this.scanner.pos;\n ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, Modifiers.None, null, true);\n (<FuncDecl>ast).fncFlags |= FncFlags.IsFunctionExpression;\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n ast.limChar = limChar;\n break;\n }\n\n if (ast == null) {\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n\n var idText = this.currentToken.getText();\n ast = this.createRef(idText, (<IdentifierToken>this.currentToken).hasEscapeSequence, minChar);\n sawId = true;\n \n ast.minChar = minChar;\n this.currentToken = this.scanner.scan();\n\n if (this.currentToken.tokenId == TokenID.Question) {\n ast.flags |= ASTFlags.PossibleOptionalParameter;\n }\n\n limChar = this.scanner.lastTokenLimChar();\n }\n }\n\n if (inCast) {\n this.checkCurrentToken(TokenID.GreaterThan, errorRecoverySet);\n }\n\n if (ast == null) {\n switch (this.currentToken.tokenId) {\n case TokenID.OpenParen:\n minChar = this.scanner.pos;\n var prevTokId = this.scanner.previousToken().tokenId;\n this.currentToken = this.scanner.scan();\n\n var couldBeLambda = prevTokId == TokenID.OpenParen || // foo(()=>{});\n prevTokId == TokenID.Comma || // foo(x,()=>{});\n prevTokId == TokenID.EqualsEquals || // var foo = ()=>{};\n prevTokId == TokenID.Colon; // var x = { foo: ()=> {} };\n\n\n if (couldBeLambda && this.currentToken.tokenId == TokenID.CloseParen) {\n parseAsLambda = true;\n expectlambdaRParen = false;\n this.currentToken = this.scanner.scan();\n }\n else if (couldBeLambda && this.currentToken.tokenId == TokenID.DotDotDot) {\n parseAsLambda = true;\n expectlambdaRParen = true;\n }\n else {\n ast = this.parseExpr(errorRecoverySet | ErrorRecoverySet.RParen,\n OperatorPrecedence.None, true, TypeContext.NoTypes, couldBeLambda);\n limChar = this.scanner.lastTokenLimChar();\n parseAsLambda = couldBeLambda && (ast.nodeType == NodeType.Name || ast.nodeType == NodeType.Comma) &&\n (this.currentToken.tokenId == TokenID.Colon || this.currentToken.tokenId == TokenID.Question);\n expectlambdaRParen = true;\n }\n\n // Check for the RParen if it's not an anonymous '=>' function\n if ((ast && !parseAsLambda)) {\n if (hasFlag(ast.flags, ASTFlags.SkipNextRParen)) {\n // REVIEW: parseExpr resulted in a lambda node, the LParen scanned earlier, is the beginning of that node, and not of a parenthesized expression;\n // do not look for a matching RParen for this node, but make sure to remove the flag, so that any enclosing parenthesis are matched correctly.\n ast.flags = ast.flags & (~(ASTFlags.SkipNextRParen)); \n break;\n }\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet);\n ast.isParenthesized = true;\n }\n\n break;\n case TokenID.NumberLiteral: {\n var numTok = <NumberLiteralToken>this.currentToken;\n this.currentToken = this.scanner.scan();\n ast = new NumberLiteral(numTok.value, numTok.hasEmptyFraction);\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n break;\n }\n case TokenID.StringLiteral:\n ast = new StringLiteral(this.currentToken.getText());\n this.currentToken = this.scanner.scan();\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n break;\n case TokenID.RegularExpressionLiteral: {\n var rtok = <RegularExpressionLiteralToken>this.currentToken;\n ast = new RegexLiteral(rtok.regex);\n this.currentToken = this.scanner.scan();\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n break;\n }\n case TokenID.OpenBracket:\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n ast = this.parseArrayLiteral(ErrorRecoverySet.RBrack | errorRecoverySet);\n ast.minChar = minChar;\n limChar = this.scanner.pos; // ']'\n this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet);\n break;\n // TODO: rescan regex for TokenID.Div and AsgDiv\n case TokenID.OpenBrace:\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n var members = this.parseMemberList(ErrorRecoverySet.RCurly | errorRecoverySet)\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n ast = new UnaryExpression(NodeType.ObjectLit, members);\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n members.minChar = minChar;\n members.limChar = limChar;\n break;\n\n case TokenID.LessThan:\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n var term: AST = this.parseTypeReference(ErrorRecoverySet.BinOp, false);\n this.checkCurrentToken(TokenID.GreaterThan, errorRecoverySet);\n ast = new UnaryExpression(NodeType.TypeAssertion, this.parseExpr(errorRecoverySet, OperatorPrecedence.Unary, false, TypeContext.NoTypes));\n (<UnaryExpression>ast).castTerm = term;\n break;\n\n default:\n if (this.prevExpr && hasFlag(this.prevExpr.flags, ASTFlags.PossibleOptionalParameter)) {\n parseAsLambda = true;\n ast = this.prevExpr;\n }\n else {\n this.reportParseError(\"Check format of expression term\");\n if (this.errorRecovery) {\n var ident = new MissingIdentifier();\n ident.minChar = minChar;\n ident.flags |= ASTFlags.Error;\n this.skip(errorRecoverySet | ErrorRecoverySet.Postfix);\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n ident.setText(this.currentToken.getText(), (<IdentifierToken>this.currentToken).hasEscapeSequence);\n this.currentToken = this.scanner.scan();\n limChar = this.scanner.lastTokenLimChar();\n }\n else {\n limChar = this.scanner.lastTokenLimChar();\n //tok=scanner.scan();\n }\n\n // REVIEW: set sawId\n ast = ident;\n }\n }\n }\n }\n\n if (parseAsLambda) {\n // If the next token is an fat arrow or a colon, we either have a parameter list, or can rightly assume\n // that we have a typed formal, so we proceed with the lambda parse\n if (\n this.currentToken.tokenId == TokenID.Colon ||\n this.currentToken.tokenId == TokenID.Comma ||\n this.currentToken.tokenId == TokenID.CloseParen ||\n this.currentToken.tokenId == TokenID.DotDotDot) {\n\n // We won't scan in the ':' case, since keeping the ':' simplifies argument handling in parseFormalParameterList\n // Note that we don't set the minchar in this case\n ast = this.parseLambdaExpr(errorRecoverySet, ast, true /* skipNextRParen */, expectlambdaRParen);\n ast.minChar = minChar;\n limChar = this.scanner.lastTokenLimChar();\n ast.limChar = limChar;\n }\n else if (ast) {\n ast.isParenthesized = true;\n }\n }\n\n if (sawId && (typeContext != TypeContext.NoTypes)) {\n typeContext |= TypeContext.ArraySuffix;\n }\n\n var postFix = this.parsePostfixOperators(errorRecoverySet, ast, allowCall, inNew, typeContext, minChar, limChar);\n\n // Defensive error check...\n if (postFix) {\n if (sawId && (postFix.nodeType == NodeType.Index)) {\n var binExpr = <BinaryExpression>postFix;\n if (binExpr.operand2 == null) {\n postFix = this.convertToTypeReference(postFix);\n }\n }\n\n ///////////////////////////////////////////////////////////\n //TODO: Eventually, we want to remove \"minChar\" and \"limChar\" assignments here,\n // as they are sometimes not specific enough for each expression kind.\n postFix.minChar = minChar;\n // Only update \"limChar\" if it is not better than \"lastTokenLimChar()\"\n postFix.limChar = max(postFix.limChar, this.scanner.lastTokenLimChar());\n //\n ///////////////////////////////////////////////////////////\n return postFix;\n }\n else {\n return new AST(NodeType.Error);\n }\n\n }\n\n private parseLambdaExpr(errorRecoverySet: ErrorRecoverySet, lambdaArgs: AST, skipNextRParen: bool, expectClosingRParen: bool): AST {\n // REVIEW: Parse the remainder of a lambda expression. The opening paren has been read already, if it existed. \n // skipNextRParen sets a flag on the resulting lambda node to tell the calling parseTerm that the LParen it scanned has been matched as part of parsing the formal parameter list\n // expectClosingRParen indicates that a closing RParen is expected, in the cases with optional parameter or more than one parameter.\n var ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, Modifiers.None, { preProcessedLambdaArgs: lambdaArgs }, expectClosingRParen);\n (<FuncDecl>ast).fncFlags |= FncFlags.IsFunctionExpression;\n (<FuncDecl>ast).fncFlags |= FncFlags.IsFatArrowFunction;\n if (!skipNextRParen) {\n ast.flags |= ASTFlags.SkipNextRParen;\n }\n ast.limChar = this.scanner.lastTokenLimChar();;\n return ast;\n }\n\n private parseExpr(errorRecoverySet: ErrorRecoverySet, minPrecedence: number, allowIn: bool,\n typeContext: TypeContext, possiblyInLambda: bool = false): AST {\n var ast: AST = null;\n var tokenInfo = lookupToken(this.currentToken.tokenId);\n var canAssign: bool = true;\n var idHint: string = null;\n var minChar = this.scanner.startPos;\n var preComments = this.parseComments();\n var exprIsAnonLambda = false;\n\n if ((tokenInfo != undefined) && (tokenInfo.unopNodeType != NodeType.None)) {\n canAssign = false;\n this.currentToken = this.scanner.scan();\n var tempExpr = this.parseExpr(ErrorRecoverySet.BinOp | errorRecoverySet,\n tokenInfo.unopPrecedence, allowIn,\n TypeContext.NoTypes);\n\n // fold unary +- into constants\n if ((tokenInfo.unopNodeType == NodeType.Pos) &&\n (tempExpr.nodeType == NodeType.NumberLit)) {\n ast = tempExpr;\n }\n else if ((tokenInfo.unopNodeType == NodeType.Neg) &&\n (tempExpr.nodeType == NodeType.NumberLit)) {\n var numLit = <NumberLiteral>tempExpr;\n numLit.value = (-numLit.value);\n if (numLit.value == 0) {\n numLit.isNegativeZero = true;\n }\n ast = tempExpr;\n }\n else {\n ast = new UnaryExpression(tokenInfo.unopNodeType, tempExpr);\n ast.limChar = tempExpr.limChar;\n }\n ast.minChar = minChar;\n }\n else {\n ast = this.parseTerm(ErrorRecoverySet.BinOp | ErrorRecoverySet.AddOp |\n errorRecoverySet, true, typeContext, false);\n var id: Identifier;\n var temp: AST;\n if (ast.nodeType == NodeType.Name) {\n id = <Identifier>ast;\n idHint = id.actualText;\n }\n else if (ast.nodeType == NodeType.Dot) {\n\n // If this is within a class declaration, and the circumstances are right, we need to\n // transform the dotted expression into a member declaration\n var subsumedExpr = false;\n\n if (this.inferPropertiesFromThisAssignment && \n (this.currentToken.tokenId == TokenID.Colon || this.currentToken.tokenId == TokenID.Equals) &&\n this.parsingClassConstructorDefinition &&\n this.nestingLevel == this.currentClassDefinition.constructorNestingLevel && // this nesting level means we're at the top-level in the constructor\n (<BinaryExpression>ast).operand1.nodeType == NodeType.This) {\n\n if ((<BinaryExpression>ast).operand2.nodeType == NodeType.Name) {\n var op2ID: Identifier = (<Identifier>(<BinaryExpression>ast).operand2);\n\n if (!this.currentClassDefinition.knownMemberNames[op2ID.actualText]) {\n ast = this.parseClassMemberVariableDeclaration(op2ID, ast.minChar, true, errorRecoverySet, Modifiers.Public);\n subsumedExpr = true;\n }\n }\n }\n\n if (!subsumedExpr) {\n temp = ast;\n while (temp.nodeType == NodeType.Dot) {\n var binExpr = <BinaryExpression>temp;\n temp = binExpr.operand2;\n }\n if (temp.nodeType == NodeType.Name) {\n id = <Identifier>temp;\n idHint = id.actualText;\n }\n }\n }\n if ((!this.scanner.lastTokenHadNewline()) &&\n ((this.currentToken.tokenId == TokenID.PlusPlus) || (this.currentToken.tokenId == TokenID.MinusMinus))) {\n canAssign = false;\n var operand = ast;\n ast = new UnaryExpression((this.currentToken.tokenId == TokenID.PlusPlus) ? NodeType.IncPost : NodeType.DecPost, operand);\n ast.limChar = this.scanner.pos;\n ast.minChar = operand.minChar;\n this.currentToken = this.scanner.scan();\n }\n }\n for (; ;) {\n tokenInfo = lookupToken(this.currentToken.tokenId);\n if ((tokenInfo == undefined) || (tokenInfo.binopNodeType == NodeType.None)) {\n break;\n }\n if ((!allowIn) && (tokenInfo.binopNodeType == NodeType.In)) {\n break;\n }\n if (tokenInfo.binopPrecedence == OperatorPrecedence.Assignment) {\n if (tokenInfo.binopPrecedence < minPrecedence) {\n break;\n }\n if (!canAssign) {\n this.reportParseError(\"illegal assignment\");\n }\n }\n else if (tokenInfo.binopPrecedence <= minPrecedence) {\n break;\n }\n\n if (possiblyInLambda && this.currentToken.tokenId == TokenID.Comma && this.scanner.getLookAheadToken().tokenId == TokenID.DotDotDot) {\n // The ellipsis can only exist in the formal list of a lambda expression, so do not attempt to parse the comma token as the comma binary operator\n // instead parse it as a lambda\n exprIsAnonLambda = true;\n canAssign = false;\n ast = this.parseLambdaExpr(errorRecoverySet, ast, false, true);\n break;\n }\n\n // Precedence is high enough. Consume the operator token.\n this.currentToken = this.scanner.scan();\n canAssign = false;\n if (tokenInfo.binopNodeType == NodeType.ConditionalExpression) {\n if (possiblyInLambda && \n ( this.currentToken.tokenId == TokenID.Equals || this.currentToken.tokenId == TokenID.Colon || this.currentToken.tokenId == TokenID.CloseParen || this.currentToken.tokenId == TokenID.Comma)) {\n // The QMark is not a ternary expression, it is a marker for optional parameter in a lambda expression.\n exprIsAnonLambda = true;\n canAssign = true;\n }\n else {\n this.prevExpr = ast;\n var whenTrue = this.parseExpr(\n errorRecoverySet | ErrorRecoverySet.Colon, OperatorPrecedence.Assignment, allowIn, TypeContext.NoTypes);\n\n // Do not hold onto the prevExpr handle\n this.prevExpr = null;\n this.checkCurrentToken(TokenID.Colon, errorRecoverySet | ErrorRecoverySet.ExprStart);\n\n var whenFalse = this.parseExpr(\n errorRecoverySet | ErrorRecoverySet.BinOp, OperatorPrecedence.Assignment, allowIn, TypeContext.NoTypes)\n ast = new ConditionalExpression(ast, whenTrue, whenFalse);\n }\n }\n else {\n var tc = TypeContext.NoTypes;\n var binExpr2: BinaryExpression;\n\n binExpr2 = new BinaryExpression(tokenInfo.binopNodeType, ast,\n this.parseExpr(errorRecoverySet |\n ErrorRecoverySet.BinOp,\n tokenInfo.binopPrecedence,\n allowIn, TypeContext.NoTypes, possiblyInLambda));\n if (binExpr2.operand2.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>binExpr2.operand2;\n funcDecl.hint = idHint;\n }\n\n binExpr2.minChar = ast.minChar;\n binExpr2.limChar = this.scanner.lastTokenLimChar();\n idHint = null;\n ast = binExpr2;\n }\n }\n if (canAssign) {\n ast.flags |= ASTFlags.Writeable;\n }\n if (!exprIsAnonLambda) {\n ///////////////////////////////////////////////////////////\n //TODO: Eventually, we want to remove \"minChar\" and \"limChar\" assignments here,\n // as they are sometimes not specific enough for each statement kind.\n ast.minChar = minChar;\n // Only update \"limChar\" if it is not better than \"lastTokenLimChar()\"\n ast.limChar = max(ast.limChar, this.scanner.lastTokenLimChar());\n //\n ///////////////////////////////////////////////////////////\n ast.preComments = preComments;\n ast.postComments = this.parseCommentsForLine(this.scanner.line);\n }\n return ast;\n }\n\n private parsePostfixOperators(errorRecoverySet: ErrorRecoverySet, ast: AST, allowCall: bool, inNew: bool,\n typeContext: TypeContext, lhsMinChar: number, lhsLimChar: number): AST {\n var count = 0;\n\n if (!ast) {\n ast = new AST(NodeType.EmptyExpr);\n ast.isParenthesized = true;\n }\n\n ast.minChar = lhsMinChar;\n ast.limChar = lhsLimChar;\n\n for (; ;) {\n switch (this.currentToken.tokenId) {\n case TokenID.OpenParen:\n if (inNew) {\n var callExpr = <CallExpression>ast;\n callExpr.arguments = this.parseArgList(errorRecoverySet);\n inNew = false;\n }\n else {\n if (!allowCall) {\n return ast;\n }\n ast = new CallExpression(NodeType.Call, ast,\n this.parseArgList(errorRecoverySet));\n ast.minChar = lhsMinChar;\n }\n ast.limChar = this.scanner.pos; // ')'\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet);\n break;\n case TokenID.OpenBracket:\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.CloseBracket) {\n if (hasFlag(typeContext, TypeContext.ArraySuffix)) {\n this.currentToken = this.scanner.scan();\n if (ast.nodeType == NodeType.TypeRef) {\n var typeRef = <TypeReference>ast;\n typeRef.arrayCount++;\n }\n else {\n ast = new BinaryExpression(NodeType.Index, ast, null);\n }\n ast.limChar = this.scanner.pos;\n break; // note early exit from case\n }\n }\n\n ast = new BinaryExpression(NodeType.Index, ast,\n this.parseExpr(errorRecoverySet | ErrorRecoverySet.RBrack,\n OperatorPrecedence.None, true,\n TypeContext.NoTypes));\n ast.minChar = lhsMinChar;\n ast.limChar = this.scanner.pos; // ']'\n this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet);\n break;\n case TokenID.Dot: {\n var name: Identifier = null;\n var curpos = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n // Don't allow reserved words if immediately after a new line and error recovery is enabled\n if ((this.currentToken.tokenId == TokenID.Identifier) || ((!this.errorRecovery || !this.scanner.lastTokenHadNewline()) && convertTokToIDName(this.currentToken))) {\n ast.flags |= ASTFlags.DotLHS;\n name = this.createRef(this.currentToken.getText(), (<IdentifierToken>this.currentToken).hasEscapeSequence, this.scanner.startPos);\n name.limChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n }\n else {\n this.reportParseError(\"Expected identifier following dot\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n ast.flags |= (ASTFlags.Error | ASTFlags.DotLHS);\n return ast;\n }\n else {\n name = new MissingIdentifier();\n }\n }\n ast = new BinaryExpression(NodeType.Dot, ast, name);\n ast.minChar = lhsMinChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n break;\n }\n case TokenID.EqualsGreaterThan:\n ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, Modifiers.None, { preProcessedLambdaArgs: ast }, false);\n (<FuncDecl>ast).fncFlags |= FncFlags.IsFunctionExpression;\n ast.minChar = lhsMinChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n break;\n default:\n return ast;\n\n }\n }\n }\n\n private parseTry(tryNode: Try, errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers): Try {\n var minChar = this.scanner.startPos;\n var preComments = this.parseComments();\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId != TokenID.OpenBrace) {\n this.reportParseError(\"Expected '{'\");\n if (this.errorRecovery) {\n var etryNode = tryNode;\n etryNode.minChar = minChar;\n etryNode.limChar = this.scanner.lastTokenLimChar();\n etryNode.flags |= ASTFlags.Error;\n return etryNode;\n }\n }\n tryNode.body = this.parseStatement(errorRecoverySet, AllowedElements.None, parentModifiers);\n tryNode.minChar = minChar;\n tryNode.limChar = tryNode.body.limChar;\n tryNode.preComments = preComments;\n tryNode.postComments = this.parseComments();\n return tryNode;\n }\n\n private parseCatch(errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers): Catch {\n var catchMinChar = this.scanner.startPos;\n var preComments = this.parseComments();\n this.currentToken = this.scanner.scan();\n this.checkCurrentToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n if ((this.currentToken.tokenId != TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n this.reportParseError(\"Expected identifier in catch header\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n\n var ecatch = new Catch(new VarDecl(new MissingIdentifier(), this.nestingLevel),\n new Statement(NodeType.Empty));\n ecatch.statement.minChar = catchMinChar;\n ecatch.statement.limChar = this.scanner.pos;\n ecatch.minChar = this.scanner.startPos;\n ecatch.limChar = this.scanner.pos;\n ecatch.flags |= ASTFlags.Error;\n return ecatch;\n }\n }\n var param = new VarDecl(Identifier.fromToken(this.currentToken), this.nestingLevel);\n param.id.minChar = this.scanner.startPos;\n param.id.limChar = this.scanner.pos;\n param.minChar = param.id.minChar;\n param.limChar = param.id.limChar;\n this.currentToken = this.scanner.scan();\n var statementPos = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.StmtStart);\n if (this.currentToken.tokenId != TokenID.OpenBrace) {\n this.reportParseError(\"Expected '{' to start catch body\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n\n var ecatch = new Catch(new VarDecl(new MissingIdentifier(), this.nestingLevel),\n new Statement(NodeType.Empty));\n ecatch.statement.minChar = catchMinChar;\n ecatch.statement.limChar = statementPos;\n ecatch.minChar = this.scanner.startPos;\n ecatch.limChar = this.scanner.pos;\n ecatch.flags |= ASTFlags.Error;\n return ecatch;\n }\n }\n\n var catchStmt = this.parseStatement(errorRecoverySet, AllowedElements.None, parentModifiers);\n var catchNode = new Catch(param, catchStmt);\n catchNode.statement.minChar = catchMinChar;\n catchNode.statement.limChar = statementPos;\n catchNode.minChar = catchMinChar;\n catchNode.limChar = catchStmt.limChar;\n catchNode.preComments = preComments;\n catchNode.postComments = this.parseComments();\n return catchNode;\n }\n\n private parseFinally(errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers): Finally {\n var finMinChar = this.scanner.startPos;\n var preComments = this.parseComments();\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId != TokenID.OpenBrace) {\n this.reportParseError(\"Expected '{' to start body of finally statement\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet);\n var efin = new Finally(new Statement(NodeType.Empty));\n efin.flags |= ASTFlags.Error;\n efin.minChar = this.scanner.startPos;\n efin.limChar = this.scanner.pos;\n return efin;\n }\n }\n\n var finBody = this.parseStatement(errorRecoverySet, AllowedElements.None, parentModifiers)\n var fin = new Finally(finBody);\n fin.minChar = finMinChar;\n fin.limChar = fin.body.limChar;\n fin.preComments = preComments;\n fin.postComments = this.parseComments();\n return fin;\n }\n\n private parseTryCatchFinally(errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers, labelList: ASTList): AST {\n var tryPart: AST = new Try(null);\n var tryMinChar = this.scanner.startPos;\n this.pushStmt(<Statement>tryPart, labelList);\n this.parseTry(<Try>tryPart, errorRecoverySet | ErrorRecoverySet.Catch, parentModifiers);\n this.popStmt();\n var tc: TryCatch = null;\n var tf: TryFinally = null;\n\n if (this.currentToken.tokenId == TokenID.Catch) {\n var catchPart = this.parseCatch(errorRecoverySet | ErrorRecoverySet.Catch, parentModifiers);\n tc = new TryCatch(<Try>tryPart, catchPart);\n tc.minChar = tryPart.minChar;\n tc.limChar = catchPart.limChar;\n }\n\n if (this.currentToken.tokenId != TokenID.Finally) {\n if (tc == null) {\n this.reportParseError(\"try with neither catch nor finally\");\n if (this.errorRecovery) {\n var etf = new TryFinally(tryPart, new Finally(new AST(NodeType.Empty)));\n etf.flags |= ASTFlags.Error;\n etf.minChar = this.scanner.startPos;\n etf.limChar = this.scanner.pos;\n return etf;\n }\n return new TryFinally(tryPart, new Finally(new AST(NodeType.Empty)));\n }\n else {\n return tc;\n }\n }\n else {\n if (tc) {\n tryPart = tc;\n }\n var finallyPart = this.parseFinally(errorRecoverySet, parentModifiers)\n tf = new TryFinally(tryPart, finallyPart);\n tf.minChar = tryMinChar;\n tf.limChar = finallyPart.limChar;\n return tf;\n }\n }\n\n private parseStatement(errorRecoverySet: ErrorRecoverySet, allowedElements: AllowedElements, parentModifiers: Modifiers): AST {\n var ast: AST = null;\n var labelList: ASTList = null;\n var astList: ASTList = null;\n var temp: AST;\n var modifiers = Modifiers.None;\n var minChar = this.scanner.startPos;\n var forInOk = false;\n var needTerminator = false;\n var fnOrVar: AST = null;\n var preComments = this.parseComments();\n this.state = ParseState.StartStatement;\n\n function isAmbient() {\n return hasFlag(modifiers, Modifiers.Ambient) || hasFlag(parentModifiers, Modifiers.Ambient);\n }\n\n function mayNotBeExported() {\n if (hasFlag(modifiers, Modifiers.Exported)) {\n this.reportError(\"Statement may not be exported\");\n }\n }\n\n for (; ;) {\n switch (this.currentToken.tokenId) {\n case TokenID.EndOfFile:\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.pos;\n break;\n case TokenID.Function:\n if (this.parsingDeclareFile || isAmbient() || this.ambientModule) {\n this.currentToken = this.scanner.scan();\n fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n modifiers, true, false);\n if (fnOrVar.nodeType == NodeType.VarDecl) {\n this.reportParseError(\"function keyword can only introduce function declaration\");\n }\n else if ((fnOrVar.nodeType == NodeType.FuncDecl) && ((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction)) {\n needTerminator = true;\n }\n ast = fnOrVar;\n if (this.parsingDeclareFile || this.ambientModule && ast.nodeType == NodeType.FuncDecl) {\n (<FuncDecl>ast).fncFlags |= FncFlags.Exported;\n }\n }\n else {\n ast = this.parseFncDecl(errorRecoverySet, true, false, false, null, false, false, isAmbient(), modifiers, null, true);\n if (hasFlag((<FuncDecl>ast).fncFlags, FncFlags.IsFatArrowFunction)) {\n needTerminator = true;\n }\n if (this.ambientModule) {\n this.reportParseError(\"function declaration not permitted within ambient module\");\n }\n if (hasFlag(modifiers, Modifiers.Exported)) {\n (<FuncDecl>ast).fncFlags |= FncFlags.Exported;\n }\n }\n break;\n case TokenID.Module:\n if ((allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None) {\n this.reportParseError(\"module not allowed in this context\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n ast = this.parseModuleDecl(errorRecoverySet, modifiers, preComments);\n preComments = null;\n }\n break;\n case TokenID.Import:\n if ((allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None) {\n this.reportParseError(\"module not allowed in this context\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n if (hasFlag(modifiers, Modifiers.Exported)) {\n this.reportParseError(\"export keyword not permitted on import declaration\");\n }\n ast = this.parseImportDeclaration(errorRecoverySet, modifiers);\n needTerminator = true;\n }\n break;\n case TokenID.Export:\n if ((allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None) {\n this.reportParseError(\"'export' statements are only allowed at the global and module levels\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n if (this.topLevel) {\n this.hasTopLevelImportOrExport = true;\n }\n modifiers |= Modifiers.Exported;\n this.currentToken = this.scanner.scan();\n break;\n case TokenID.Private:\n modifiers |= Modifiers.Private;\n\n this.currentToken = this.scanner.scan();\n\n if (this.parsingClassConstructorDefinition) {\n\n if (!this.inferPropertiesFromThisAssignment) {\n this.reportParseError(\"Property declarations are not permitted within constructor bodies\");\n }\n\n minChar = this.scanner.pos;\n if (this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId != TokenID.This || (this.currentToken = this.scanner.scan()).tokenId != TokenID.Dot)) {\n this.reportParseError(\"Expected 'this.' for property declaration\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n this.currentToken = this.scanner.scan();\n\n var id = Identifier.fromToken(this.currentToken);\n id.minChar = this.scanner.startPos;\n id.limChar = this.scanner.pos;\n\n this.currentToken = this.scanner.scan();\n ast = this.parseClassMemberVariableDeclaration(id, minChar, this.parsingClassConstructorDefinition, errorRecoverySet, modifiers);\n }\n }\n else {\n if (this.currentToken.tokenId != TokenID.Interface) {\n if (this.currentToken.tokenId == TokenID.Get) {\n this.prevIDTok = this.currentToken;\n this.currentToken = this.scanner.scan();\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n modifiers |= Modifiers.Getter;\n this.prevIDTok = null;\n }\n }\n else if (this.currentToken.tokenId == TokenID.Set) {\n this.prevIDTok = this.currentToken;\n this.currentToken = this.scanner.scan();\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n modifiers |= Modifiers.Setter;\n this.prevIDTok = null;\n }\n }\n fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n modifiers, isAmbient(), false);\n if ((fnOrVar.nodeType == NodeType.VarDecl) ||\n ((fnOrVar.nodeType == NodeType.FuncDecl) && (hasFlag((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction)))) {\n needTerminator = true;\n }\n ast = fnOrVar;\n }\n }\n break;\n case TokenID.Public:\n if (this.parsingClassConstructorDefinition) {\n\n if (!this.inferPropertiesFromThisAssignment) {\n this.reportParseError(\"Property declarations are not permitted within constructor bodies\");\n }\n\n this.currentToken = this.scanner.scan(); \n minChar = this.scanner.pos;\n modifiers |= Modifiers.Public;\n if (this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId != TokenID.This || (this.currentToken = this.scanner.scan()).tokenId != TokenID.Dot)) {\n this.reportParseError(\"Expected 'this.' for property declaration\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n this.currentToken = this.scanner.scan();\n\n var id = Identifier.fromToken(this.currentToken);\n id.minChar = this.scanner.startPos;\n id.limChar = this.scanner.pos;\n\n this.currentToken = this.scanner.scan();\n ast = this.parseClassMemberVariableDeclaration(id, minChar, this.parsingClassConstructorDefinition, errorRecoverySet, modifiers);\n }\n }\n else {\n if ((allowedElements & AllowedElements.Properties) == AllowedElements.None) {\n this.reportParseError(\"'property' statements are only allowed within classes\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n modifiers |= Modifiers.Public;\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.Get) {\n this.prevIDTok = this.currentToken;\n this.currentToken = this.scanner.scan();\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n modifiers |= Modifiers.Getter;\n this.prevIDTok = null;\n }\n }\n else if (this.currentToken.tokenId == TokenID.Set) {\n this.prevIDTok = this.currentToken;\n this.currentToken = this.scanner.scan();\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n modifiers |= Modifiers.Setter;\n this.prevIDTok = null;\n }\n }\n fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n modifiers, isAmbient(), false);\n if ((fnOrVar.nodeType == NodeType.VarDecl) ||\n ((fnOrVar.nodeType == NodeType.FuncDecl) && hasFlag((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction))) {\n needTerminator = true;\n }\n ast = fnOrVar;\n }\n }\n break;\n case TokenID.Declare:\n if (!(allowedElements & AllowedElements.AmbientDeclarations)) {\n this.reportParseError(\"Ambient declarations are only allowed at the top-level or module scopes\")\n }\n if (!this.parsingDeclareFile && hasFlag(parentModifiers, Modifiers.Ambient)) {\n this.reportParseError(\"Duplicate ambient declaration in this context. (Is the enclosing module or class already ambient?)\")\n }\n modifiers |= Modifiers.Ambient;\n this.currentToken = this.scanner.scan();\n break;\n case TokenID.Class:\n if ((allowedElements & AllowedElements.ClassDeclarations) == AllowedElements.None) {\n this.reportParseError(\"class not allowed in this context\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n ast = this.parseClassDecl(errorRecoverySet, minChar, modifiers);\n }\n break;\n case TokenID.Interface:\n if ((allowedElements & AllowedElements.InterfaceDeclarations) == AllowedElements.None) {\n this.reportParseError(\"interface not allowed in this context\");\n this.currentToken = this.scanner.scan();\n ast = new AST(NodeType.Error);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n }\n else {\n ast = this.parseInterfaceDecl(errorRecoverySet, modifiers);\n }\n break;\n case TokenID.Var:\n var declAst: AST = this.parseVariableDeclaration(errorRecoverySet | ErrorRecoverySet.StmtStart, modifiers,\n true, false);\n if (declAst.nodeType == NodeType.VarDecl) {\n ast = declAst;\n }\n else {\n ast = new Block(<ASTList>declAst, false);\n }\n needTerminator = true;\n break;\n case TokenID.Static:\n\n if (this.currentClassDecl == null) {\n this.reportParseError(\"Statics may only be class members\");\n }\n\n mayNotBeExported();\n modifiers |= Modifiers.Public;\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.Get) {\n this.prevIDTok = this.currentToken;\n this.currentToken = this.scanner.scan();\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n modifiers |= Modifiers.Getter;\n this.prevIDTok = null;\n }\n }\n else if (this.currentToken.tokenId == TokenID.Set) {\n this.currentToken = this.scanner.scan();\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n }\n if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n modifiers |= Modifiers.Setter;\n }\n }\n if (isAmbient()) {\n modifiers |= Modifiers.Ambient;\n }\n fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n modifiers, this.parsingDeclareFile || (modifiers & Modifiers.Ambient) != Modifiers.None, true);\n\n var staticsList = this.topStaticsList();\n if (staticsList && fnOrVar.nodeType == NodeType.VarDecl) {\n staticsList.append(fnOrVar);\n }\n\n if (fnOrVar.nodeType == NodeType.VarDecl || ((fnOrVar.nodeType == NodeType.FuncDecl) && hasFlag((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction))) {\n needTerminator = true;\n }\n\n ast = fnOrVar;\n break;\n case TokenID.For:\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"syntax error: for statement does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart | ErrorRecoverySet.Var);\n this.state = ParseState.ForInit;\n forInOk = true;\n switch (this.currentToken.tokenId) {\n case TokenID.Var:\n temp = this.parseVariableDeclaration(errorRecoverySet | ErrorRecoverySet.SColon |\n ErrorRecoverySet.In, Modifiers.None, false, false);\n break;\n case TokenID.Semicolon:\n temp = null;\n this.state = ParseState.ForCondStart;\n break;\n default:\n temp = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon |\n ErrorRecoverySet.In, OperatorPrecedence.None, false,\n TypeContext.NoTypes);\n break;\n }\n this.state = ParseState.ForInitAfterVar;\n if (this.currentToken.tokenId == TokenID.In) {\n if ((temp == null) || (!forInOk)) {\n this.reportParseError(\"malformed for statement\");\n if (this.errorRecovery) {\n this.skip(errorRecoverySet | ErrorRecoverySet.StmtStart);\n ast = new AST(NodeType.Empty);\n ast.flags |= ASTFlags.Error;\n }\n }\n else {\n this.currentToken = this.scanner.scan();\n var forInStmt = new ForInStatement(temp,\n this.parseExpr(ErrorRecoverySet.RParen |\n errorRecoverySet,\n OperatorPrecedence.Comma,\n false,\n TypeContext.NoTypes));\n\n forInStmt.limChar = this.scanner.pos;\n forInStmt.statement.minChar = minChar;\n forInStmt.statement.limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseParen, ErrorRecoverySet.StmtStart | errorRecoverySet);\n this.pushStmt(forInStmt, labelList);\n forInStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n this.popStmt();\n forInStmt.minChar = minChar;\n ast = forInStmt;\n }\n }\n else {\n var forStmt: ForStatement = new ForStatement(temp);\n forStmt.minChar = minChar;\n this.checkCurrentToken(TokenID.Semicolon, errorRecoverySet);\n if (this.currentToken.tokenId == TokenID.Semicolon) {\n forStmt.cond = null;\n }\n else {\n forStmt.cond = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon |\n ErrorRecoverySet.RParen,\n OperatorPrecedence.None, true,\n TypeContext.NoTypes);\n if (this.currentToken.tokenId != TokenID.Semicolon) {\n this.skip(errorRecoverySet | ErrorRecoverySet.StmtStart);\n ast = forStmt;\n ast.flags |= ASTFlags.Error;\n }\n }\n this.currentToken = this.scanner.scan();\n if (this.currentToken.tokenId == TokenID.CloseParen) {\n forStmt.incr = null;\n }\n else {\n forStmt.incr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon |\n ErrorRecoverySet.RParen,\n OperatorPrecedence.None, true,\n TypeContext.NoTypes);\n }\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly);\n this.pushStmt(forStmt, labelList);\n forStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n this.popStmt();\n forStmt.limChar = forStmt.body.limChar;\n ast = forStmt;\n }\n break;\n case TokenID.With: {\n if (codeGenTarget < CodeGenTarget.ES5) {\n this.reportParseError(\"'with' statements are only available in ES5 codegen mode or better\");\n }\n\n if (this.strictMode) {\n this.reportParseError(\"'with' statements are not available in strict mode\");\n }\n\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"'with' statement does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart | ErrorRecoverySet.Var);\n\n var expr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.Colon,\n OperatorPrecedence.None, true,\n TypeContext.NoTypes);\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly);\n\n var withStmt = new WithStatement(expr);\n withStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n withStmt.minChar = minChar;\n withStmt.limChar = withStmt.body.limChar;\n ast = withStmt;\n }\n break;\n case TokenID.Switch: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"'switch' statement does not take modifiers\");\n }\n this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n\n var switchStmt = new SwitchStatement(this.parseExpr(errorRecoverySet |\n ErrorRecoverySet.RParen,\n OperatorPrecedence.None,\n true,\n TypeContext.NoTypes));\n switchStmt.statement.minChar = minChar;\n switchStmt.statement.limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly);\n var caseListMinChar = this.scanner.startPos;\n this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.SCase);\n switchStmt.defaultCase = null;\n switchStmt.caseList = new ASTList();\n var caseStmt: CaseStatement = null;\n this.pushStmt(switchStmt, labelList);\n for (; ;) {\n if ((this.currentToken.tokenId == TokenID.Case) ||\n (this.currentToken.tokenId == TokenID.Default)) {\n var isDefault = (this.currentToken.tokenId == TokenID.Default);\n caseStmt = new CaseStatement();\n caseStmt.minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n if (isDefault) {\n switchStmt.defaultCase = caseStmt;\n }\n else {\n caseStmt.expr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.Colon,\n OperatorPrecedence.None, true,\n TypeContext.NoTypes);\n }\n this.checkCurrentToken(TokenID.Colon, errorRecoverySet | ErrorRecoverySet.StmtStart);\n caseStmt.body = new ASTList();\n this.parseStatementList(errorRecoverySet | ErrorRecoverySet.RCurly,\n caseStmt.body, false, true, allowedElements, modifiers);\n caseStmt.limChar = caseStmt.body.limChar;\n switchStmt.caseList.append(caseStmt);\n }\n else {\n break;\n }\n }\n // end of switch statement\n switchStmt.caseList.minChar = caseListMinChar;\n switchStmt.caseList.limChar = this.scanner.pos;\n switchStmt.limChar = switchStmt.caseList.limChar;\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n this.popStmt();\n ast = switchStmt;\n break;\n }\n case TokenID.While: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"'while' statement does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n this.checkNextToken(TokenID.OpenParen, ErrorRecoverySet.ExprStart |\n errorRecoverySet);\n var whileStmt = new WhileStatement(this.parseExpr(errorRecoverySet |\n ErrorRecoverySet.RParen,\n OperatorPrecedence.None,\n true, TypeContext.NoTypes));\n whileStmt.minChar = minChar;\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet |\n ErrorRecoverySet.StmtStart);\n this.pushStmt(whileStmt, labelList);\n whileStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n whileStmt.limChar = whileStmt.body.limChar;\n this.popStmt();\n ast = whileStmt;\n break;\n }\n case TokenID.Do: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"'do' statement does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n var doStmt = new DoWhileStatement();\n doStmt.minChar = minChar;\n this.pushStmt(doStmt, labelList);\n doStmt.body = this.parseStatement(errorRecoverySet | ErrorRecoverySet.While,\n allowedElements, parentModifiers);\n this.popStmt();\n doStmt.whileAST = new Identifier(\"while\");\n doStmt.whileAST.minChar = this.scanner.startPos;\n this.checkCurrentToken(TokenID.While, errorRecoverySet | ErrorRecoverySet.LParen);\n doStmt.whileAST.limChar = doStmt.whileAST.minChar + 5;\n this.checkCurrentToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n doStmt.cond = this.parseExpr(errorRecoverySet | ErrorRecoverySet.RParen,\n OperatorPrecedence.None, true, TypeContext.NoTypes);\n doStmt.limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet);\n ast = doStmt;\n // compatibility; more strict would be to require the ';'\n if (this.currentToken.tokenId == TokenID.Semicolon) {\n this.currentToken = this.scanner.scan();\n }\n break;\n }\n case TokenID.If: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"if statement does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n var ifStmt = new IfStatement(this.parseExpr(errorRecoverySet |\n ErrorRecoverySet.LParen,\n OperatorPrecedence.None, true,\n TypeContext.NoTypes));\n ifStmt.minChar = minChar;\n ifStmt.statement.minChar = minChar;\n ifStmt.statement.limChar = this.scanner.pos;\n this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.StmtStart);\n this.pushStmt(ifStmt, labelList);\n ifStmt.thenBod = this.parseStatement(ErrorRecoverySet.Else | errorRecoverySet,\n allowedElements, parentModifiers);\n ifStmt.limChar = ifStmt.thenBod.limChar;\n if (this.currentToken.tokenId == TokenID.Else) {\n this.currentToken = this.scanner.scan();\n ifStmt.elseBod = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n ifStmt.limChar = ifStmt.elseBod.limChar;\n }\n this.popStmt();\n ast = ifStmt;\n break;\n }\n case TokenID.Try: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"try statement does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n ast = this.parseTryCatchFinally(errorRecoverySet, parentModifiers, labelList);\n break;\n }\n case TokenID.OpenBrace: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"block does not take modifiers\");\n }\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n var block = new Block(new ASTList(), true);\n this.pushStmt(block, labelList);\n this.parseStatementList(\n errorRecoverySet | ErrorRecoverySet.RCurly, block.statements,\n /*sourceElements:*/ false, /*noLeadingCase:*/ false, AllowedElements.None, modifiers);\n this.popStmt();\n block.statements.minChar = minChar;\n block.statements.limChar = this.scanner.pos;\n block.minChar = block.statements.minChar;\n block.limChar = block.statements.limChar;\n this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n ast = block;\n break;\n }\n case TokenID.Semicolon:\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"modifier can not appear here\");\n }\n ast = new AST(NodeType.Empty);\n this.currentToken = this.scanner.scan();\n break;\n case TokenID.Break:\n case TokenID.Continue: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"modifiers can not appear before jump statement\");\n }\n var jump =\n new Jump((this.currentToken.tokenId == TokenID.Break) ? NodeType.Break : NodeType.Continue);\n this.currentToken = this.scanner.scan();\n if ((this.currentToken.tokenId == TokenID.Identifier) && (!this.scanner.lastTokenHadNewline())) {\n // Labeled break or continue.\n jump.target = this.currentToken.getText();\n this.currentToken = this.scanner.scan();\n }\n this.resolveJumpTarget(jump);\n ast = jump;\n needTerminator = true;\n break;\n }\n case TokenID.Return: {\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"modifiers can not appear before return statement\");\n }\n if (!this.inFunction) {\n this.reportParseError(\"return statement outside of function body\");\n }\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n var retStmt = new ReturnStatement();\n retStmt.minChar = minChar;\n if ((this.currentToken.tokenId != TokenID.Semicolon) &&\n (this.currentToken.tokenId != TokenID.CloseBrace) &&\n (!(this.scanner.lastTokenHadNewline()))) {\n retStmt.returnExpression = this.parseExpr(errorRecoverySet |\n ErrorRecoverySet.SColon,\n OperatorPrecedence.None,\n true, TypeContext.NoTypes);\n }\n needTerminator = true;\n retStmt.limChar = this.scanner.lastTokenLimChar();\n ast = retStmt;\n break;\n }\n case TokenID.Throw:\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"modifiers can not appear before a throw statement\");\n }\n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n if ((this.currentToken.tokenId != TokenID.Semicolon) &&\n (this.currentToken.tokenId != TokenID.CloseBrace) &&\n (!(this.scanner.lastTokenHadNewline()))) {\n temp = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n OperatorPrecedence.None, true, TypeContext.NoTypes);\n }\n else {\n this.reportParseError(\"throw with no target\");\n temp = null;\n }\n ast = new UnaryExpression(NodeType.Throw, temp);\n ast.limChar = this.scanner.lastTokenLimChar();\n needTerminator = true;\n break;\n case TokenID.Enum:\n // TODO: check module allowed here\n //minChar=scanner.startPos;\n this.currentToken = this.scanner.scan();\n ast = this.parseEnumDecl(errorRecoverySet, modifiers);\n ast.minChar = minChar;\n ast.limChar = this.scanner.lastTokenLimChar();\n if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n (<ModuleDeclaration>ast).modFlags |= ModuleFlags.Ambient;\n }\n if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n (<ModuleDeclaration>ast).modFlags |= ModuleFlags.Exported;\n }\n break;\n case TokenID.Debugger:\n mayNotBeExported();\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"modifiers can not appear before debugger statement\");\n }\n \n minChar = this.scanner.startPos;\n this.currentToken = this.scanner.scan();\n var debuggerStmt = new DebuggerStatement();\n debuggerStmt.minChar = minChar;\n needTerminator = true;\n debuggerStmt.limChar = this.scanner.lastTokenLimChar();\n ast = debuggerStmt;\n break;\n default:\n if (modifiers != Modifiers.None) {\n this.reportParseError(\"modifiers can not appear before an expression statement or label\");\n }\n minChar = this.scanner.startPos;\n var svPos = this.scanner.pos;\n temp = this.parseExpr(ErrorRecoverySet.Colon | ErrorRecoverySet.StmtStart |\n errorRecoverySet, OperatorPrecedence.None, true,\n TypeContext.NoTypes);\n if (this.scanner.pos == svPos) {\n // no progress\n this.currentToken = this.scanner.scan();\n ast = temp;\n }\n else if ((this.currentToken.tokenId == TokenID.Colon) && (!this.scanner.lastTokenHadNewline()) &&\n temp && (temp.nodeType == NodeType.Name)) {\n // It's a label\n if (labelList == null) {\n labelList = new ASTList();\n }\n labelList.append(new Label(<Identifier>temp));\n this.currentToken = this.scanner.scan();\n }\n else {\n // expression statement\n ast = temp;\n needTerminator = true;\n }\n }\n if (ast) {\n break;\n }\n }\n if (needTerminator) {\n switch (this.currentToken.tokenId) {\n case TokenID.Semicolon:\n this.currentToken = this.scanner.scan();\n ast.flags |= ASTFlags.ExplicitSemicolon;\n break;\n case TokenID.EndOfFile:\n // Extend any incomplete statements to include EOF token. This makes sure that this node is in the path \n // when completion or parameter help is requested.\n ast.limChar = this.scanner.pos;\n // IntentionaCloseBracethrough\n case TokenID.CloseBrace:\n ast.flags |= ASTFlags.AutomaticSemicolon;\n if (this.style_requireSemi) {\n this.reportParseStyleError(\"no automatic semicolon\");\n }\n break;\n default:\n if (!this.scanner.lastTokenHadNewline()) {\n this.reportParseError(\"Expected ';'\");\n }\n else {\n ast.flags |= ASTFlags.AutomaticSemicolon;\n if (this.style_requireSemi) {\n this.reportParseStyleError(\"no automatic semicolon\");\n }\n }\n break;\n }\n }\n if (labelList) {\n ast = new LabeledStatement(labelList, ast);\n }\n\n ///////////////////////////////////////////////////////////\n //TODO: Eventually, we want to remove \"minChar\" and \"limChar\" assignments here,\n // as they are sometimes not specific enough for each statement kind.\n ast.minChar = minChar;\n // Only update \"limChar\" if it is not better than \"lastTokenLimChar()\"\n ast.limChar = max(ast.limChar, this.scanner.lastTokenLimChar());\n //\n ///////////////////////////////////////////////////////////\n\n if (preComments) {\n ast.preComments = preComments;\n }\n if (this.ambientModule && (!this.okAmbientModuleMember(ast))) {\n this.reportParseError(\"statement not permitted within ambient module\");\n }\n ast.flags |= ASTFlags.IsStatement;\n return ast;\n }\n\n private okAmbientModuleMember(ast: AST) {\n var nt = ast.nodeType;\n return (nt == NodeType.ClassDeclaration) || (nt == NodeType.ImportDeclaration) || (nt == NodeType.InterfaceDeclaration) || (nt == NodeType.ModuleDeclaration) ||\n (nt == NodeType.Empty) || (nt == NodeType.VarDecl) || \n ((nt == NodeType.Block) && !(<Block>ast).isStatementBlock) ||\n ((nt == NodeType.FuncDecl) && ((<FuncDecl>ast).isMethod()));\n }\n\n private parseStatementList(errorRecoverySet: ErrorRecoverySet,\n statements: ASTList,\n sourceElms: bool,\n noLeadingCase: bool,\n allowedElements: AllowedElements,\n parentModifiers: Modifiers): void {\n var directivePrologue = sourceElms;\n statements.minChar = this.scanner.startPos;\n var limChar = this.scanner.pos;\n var innerStmts = (allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None;\n var classNope = (allowedElements & AllowedElements.ClassDeclarations) == AllowedElements.None;\n\n errorRecoverySet |= ErrorRecoverySet.TypeScriptS | ErrorRecoverySet.RCurly;\n\n this.state = ParseState.StartStatementList;\n var oldStrictMode = this.strictMode;\n this.nestingLevel++;\n for (; ;) {\n if ((this.currentToken.tokenId == TokenID.CloseBrace) ||\n (noLeadingCase && ((this.currentToken.tokenId == TokenID.Case) || (this.currentToken.tokenId == TokenID.Default))) ||\n (innerStmts && (this.currentToken.tokenId == TokenID.Export)) ||\n (classNope && (this.currentToken.tokenId == TokenID.Class)) ||\n (this.currentToken.tokenId == TokenID.EndOfFile)) {\n this.state = ParseState.EndStmtList;\n statements.limChar = limChar;\n if (statements.members.length == 0) {\n statements.preComments = this.parseComments();\n }\n else {\n statements.postComments = this.parseComments();\n }\n this.strictMode = oldStrictMode;\n this.nestingLevel--;\n return;\n }\n\n var stmt = this.parseStatement(errorRecoverySet &\n (~(ErrorRecoverySet.Else | ErrorRecoverySet.RParen |\n ErrorRecoverySet.Catch | ErrorRecoverySet.Colon)),\n allowedElements, parentModifiers);\n\n\n if (stmt) {\n stmt.postComments = this.combineComments(stmt.postComments, this.parseCommentsForLine(this.scanner.prevLine));\n statements.append(stmt);\n limChar = stmt.limChar;\n if (directivePrologue) {\n if (stmt.nodeType == NodeType.QString) {\n var qstring = <StringLiteral>stmt;\n if (qstring.text == \"\\\"use strict\\\"\") {\n statements.flags |= ASTFlags.StrictMode;\n this.strictMode = true;\n }\n else {\n directivePrologue = false;\n }\n }\n else {\n directivePrologue = false;\n }\n }\n }\n }\n }\n\n private fname = \"\";\n\n public quickParse(sourceText: ISourceText, filename: string, unitIndex: number): QuickParseResult {\n //TODO: REVIEW: We set this to avoid adding a \"module\" decl in the resulting script (see parse() method)\n var svGenTarget = TypeScript.moduleGenTarget;\n try {\n TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Local;\n var script = this.parse(sourceText, filename, unitIndex, AllowedElements.QuickParse);\n return new QuickParseResult(script, this.scanner.lexState);\n }\n finally {\n TypeScript.moduleGenTarget = svGenTarget;\n }\n }\n\n public parse(sourceText: ISourceText, filename: string, unitIndex: number, allowedElements = AllowedElements.Global): Script {\n // Reset all parser state here. This allows us to be resilient to reentrancy if an \n // exception is thrown.\n this.fname = filename;\n this.currentUnitIndex = unitIndex;\n\n this.currentToken = null;\n this.needTerminator = false;\n this.inFunction = false;\n this.inInterfaceDecl = false;\n this.inFncDecl = false;\n this.state = ParseState.StartStatementList;\n this.ambientModule = false;\n this.ambientClass = false;\n this.topLevel = true;\n this.allowImportDeclaration = true;\n this.prevIDTok = null;\n this.statementInfoStack = new IStatementInfo[];\n this.hasTopLevelImportOrExport = false;\n this.strictMode = false;\n this.nestingLevel = 0;\n this.prevExpr = null;\n this.currentClassDefinition = null;\n this.parsingClassConstructorDefinition = false;\n this.parsingDeclareFile = false;\n this.amdDependencies = [];\n this.inferPropertiesFromThisAssignment = false;\n this.requiresExtendsBlock = false;\n\n this.scanner.resetComments();\n this.scanner.setErrorHandler((message) =>this.reportParseError(message));\n this.scanner.setSourceText(sourceText, LexMode.File);\n\n var leftCurlyCount = this.scanner.leftCurlyCount;\n var rightCurlyCount = this.scanner.rightCurlyCount;\n\n var minChar = this.scanner.pos;\n this.currentToken = this.scanner.scan();\n this.pushDeclLists();\n var bod = new ASTList();\n bod.minChar = minChar;\n\n this.state = ParseState.StartScript;\n this.parsingDeclareFile = isDSTRFile(filename) || isDTSFile(filename);\n\n while (true) {\n this.parseStatementList(\n ErrorRecoverySet.EOF | ErrorRecoverySet.Func,\n bod, /*sourceElements:*/ true, /*noLeadingCase:*/ false,\n allowedElements, Modifiers.None);\n\n if (this.currentToken.tokenId === TokenID.EndOfFile) {\n break;\n }\n\n // Still have remaining tokens in the file. Report error for this unexpected token,\n // skip it, and continue trying to parse statements until we're done. \n var badToken = tokenTable[this.currentToken.tokenId];\n this.reportParseError(\"Unexpected statement block terminator '\" + badToken.text + \"'\");\n\n this.currentToken = this.scanner.scan();\n }\n\n this.state = ParseState.EndScript;\n\n bod.limChar = this.scanner.pos;\n\n var topLevelMod: ModuleDeclaration = null;\n if (moduleGenTarget != ModuleGenTarget.Local && this.hasTopLevelImportOrExport) {\n var correctedFileName = switchToForwardSlashes(filename);\n var id: Identifier = new Identifier(correctedFileName);\n topLevelMod = new ModuleDeclaration(id, bod, this.topVarList(), this.topScopeList(), null);\n\n topLevelMod.modFlags |= ModuleFlags.IsDynamic;\n topLevelMod.modFlags |= ModuleFlags.IsWholeFile;\n topLevelMod.modFlags |= ModuleFlags.Exported;\n\n if (this.parsingDeclareFile) {\n topLevelMod.modFlags |= ModuleFlags.Ambient;\n }\n\n topLevelMod.minChar = minChar;\n topLevelMod.limChar = this.scanner.pos;\n topLevelMod.prettyName = getPrettyName(correctedFileName);\n topLevelMod.containsUnicodeChar = this.scanner.seenUnicodeChar;\n topLevelMod.containsUnicodeCharInComment = this.scanner.seenUnicodeCharInComment;\n\n topLevelMod.amdDependencies = this.amdDependencies;\n\n bod = new ASTList();\n bod.minChar = topLevelMod.minChar;\n bod.limChar = topLevelMod.limChar;\n bod.append(topLevelMod);\n }\n\n var script = new Script(this.topVarList(), this.topScopeList());\n script.bod = bod;\n this.popDeclLists();\n script.minChar = minChar;\n script.limChar = this.scanner.pos;\n script.locationInfo = new LocationInfo(filename, this.scanner.lineMap, unitIndex);\n script.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n script.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n script.isDeclareFile = this.parsingDeclareFile;\n script.topLevelMod = topLevelMod;\n script.containsUnicodeChar = this.scanner.seenUnicodeChar;\n script.containsUnicodeCharInComment = this.scanner.seenUnicodeCharInComment;\n script.requiresExtendsBlock = this.requiresExtendsBlock;\n return script;\n }\n }\n\n export function quickParse(logger: TypeScript.ILogger, scopeStartAST: AST, sourceText: ISourceText, minChar: number, limChar: number,\n errorCapture: (minChar: number, charLen: number, message: string, unitIndex: number) => void ): QuickParseResult {\n\n var fragment = sourceText.getText(minChar, limChar);\n logger.log(\"Quick parse range (\" + minChar + \",\" + limChar + \"): \\\"\" + TypeScript.stringToLiteral(fragment, 100) + \"\\\"\");\n\n var quickParser = new Parser();\n quickParser.setErrorRecovery(null);\n quickParser.errorCallback = errorCapture;\n\n // REVIEW: use enclosing scope to determine this\n // REVIEW: Why even use class here?\n var quickClassDecl = new ClassDeclaration(null, null, null, null);\n quickParser.currentClassDecl = quickClassDecl;\n\n var result = quickParser.quickParse(new StringSourceText(fragment), \"\", 0);\n return result;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n // We need to catch both left and right quotes\n // (depending on your editor's font, this may not be clear...) \n export function stripQuotes(str: string) {\n return str.replace(\"\\\"\", \"\").replace(\"'\", \"\").replace(\"'\", \"\").replace(\"\\\"\", \"\")\n }\n\n export function isQuoted(str: string) {\n return str.indexOf(\"\\\"\") != -1 || str.indexOf(\"'\") != -1 || str.indexOf(\"'\") != -1 || str.indexOf(\"\\\"\") != -1;\n }\n\n export function quoteStr(str: string) {\n return \"\\\"\" + str + \"\\\"\";\n }\n\n export function swapQuotes(str: string) {\n\n if (str.indexOf(\"\\\"\") != -1) {\n str = str.replace(\"\\\"\", \"'\");\n str = str.replace(\"\\\"\", \"'\");\n }\n else {\n str = str.replace(\"'\", \"\\\"\");\n str = str.replace(\"'\", \"\\\"\");\n }\n\n return str;\n }\n\n export function switchToForwardSlashes(path: string) {\n return path.replace(/\\\\/g, \"/\");\n }\n\n export function trimModName(modName: string) {\n // in case's it's a declare file...\n if (modName.length > 6 && modName.substring(modName.length - 6, modName.length) == \".d.str\") {\n return modName.substring(0, modName.length - 6);\n }\n if (modName.length > 4 && modName.substring(modName.length - 4, modName.length) == \".str\") {\n return modName.substring(0, modName.length - 4);\n }\n if (modName.length > 5 && modName.substring(modName.length - 5, modName.length) == \".d.ts\") {\n return modName.substring(0, modName.length - 5);\n }\n if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) == \".ts\") {\n return modName.substring(0, modName.length - 3);\n }\n // in case's it's a .js file\n if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) == \".js\") {\n return modName.substring(0, modName.length - 3);\n }\n\n return modName;\n }\n\n export function getDeclareFilePath(fname: string) {\n return isSTRFile(fname) ? changePathToDSTR(fname) : isTSFile(fname) ? changePathToDTS(fname) : changePathToDTS(fname);\n }\n\n function isFileOfExtension(fname: string, ext: string) {\n var invariantFname = fname.toLocaleUpperCase();\n var invariantExt = ext.toLocaleUpperCase();\n var extLength = invariantExt.length;\n return invariantFname.length > extLength && invariantFname.substring(invariantFname.length - extLength, invariantFname.length) == invariantExt;\n }\n\n export function isJSFile(fname: string) {\n return isFileOfExtension(fname, \".js\");\n }\n\n export function isSTRFile(fname: string) {\n return isFileOfExtension(fname, \".str\");\n }\n\n export function isTSFile(fname: string) {\n return isFileOfExtension(fname, \".ts\");\n }\n\n export function isDSTRFile(fname: string) {\n return isFileOfExtension(fname, \".d.str\");\n }\n\n export function isDTSFile(fname: string) {\n return isFileOfExtension(fname, \".d.ts\");\n }\n\n export function getPrettyName(modPath: string, quote?=true, treatAsFileName?=false) { \n var modName = treatAsFileName ? switchToForwardSlashes(modPath) : trimModName(stripQuotes(modPath));\n var components = this.getPathComponents(modName);\n return components.length ? (quote ? quoteStr(components[components.length - 1]) : components[components.length - 1]) : modPath;\n }\n\n export function getPathComponents(path: string) {\n return path.split(\"/\");\n }\n\n export function getRelativePathToFixedPath(fixedModFilePath: string, absoluteModPath: string) {\n absoluteModPath = switchToForwardSlashes(absoluteModPath);\n\n var modComponents = this.getPathComponents(absoluteModPath);\n var fixedModComponents = this.getPathComponents(fixedModFilePath);\n\n // Find the component that differs\n var joinStartIndex = 0;\n for (; joinStartIndex < modComponents.length && joinStartIndex < fixedModComponents.length ; joinStartIndex++) {\n if (fixedModComponents[joinStartIndex] != modComponents[joinStartIndex]) {\n break;\n }\n }\n\n // Get the relative path\n if (joinStartIndex != 0) {\n var relativePath = \"\";\n var relativePathComponents = modComponents.slice(joinStartIndex, modComponents.length);\n for (; joinStartIndex < fixedModComponents.length; joinStartIndex++) {\n if (fixedModComponents[joinStartIndex] != \"\") {\n relativePath = relativePath + \"../\";\n }\n }\n\n return relativePath + relativePathComponents.join(\"/\");\n }\n\n return absoluteModPath;\n }\n\n export function quoteBaseName(modPath: string) {\n var modName = trimModName(stripQuotes(modPath));\n var path = getRootFilePath(modName);\n if (path == \"\") {\n return modPath;\n }\n else {\n var components = modName.split(path);\n var fileIndex = components.length > 1 ? 1 : 0;\n return quoteStr(components[fileIndex]);\n }\n }\n\n export function changePathToSTR(modPath: string) {\n return trimModName(stripQuotes(modPath)) + \".str\";\n }\n\n export function changePathToDSTR(modPath: string) {\n return trimModName(stripQuotes(modPath)) + \".d.str\";\n }\n\n export function changePathToTS(modPath: string) {\n return trimModName(stripQuotes(modPath)) + \".ts\";\n }\n\n export function changePathToDTS(modPath: string) {\n return trimModName(stripQuotes(modPath)) + \".d.ts\";\n }\n\n export function isRelative(path: string) {\n return path.charAt(0) == \".\";\n }\n export function isRooted(path: string) {\n return path.charAt(0) == \"\\\\\" || path.charAt(0) == \"/\" || (path.indexOf(\":\\\\\") != -1) || (path.indexOf(\":/\") != -1);\n }\n\n export function getRootFilePath(outFname: string) {\n if (outFname == \"\") {\n return outFname;\n }\n else {\n var isPath = outFname.indexOf(\"/\") != -1;\n return isPath ? filePath(outFname) : \"\";\n }\n }\n\n export function filePathComponents(fullPath: string) {\n fullPath = switchToForwardSlashes(fullPath);\n var components = getPathComponents(fullPath);\n return components.slice(0, components.length - 1);\n }\n\n export function filePath(fullPath: string) {\n var path = filePathComponents(fullPath);\n return path.join(\"/\") + \"/\";\n }\n\n export function normalizeURL(url: string): string {\n var hostDomainAndPortRegex = /^(https?:\\/\\/[\\-\\w\\.]+(:\\d+)?\\/)(.*)$/i;\n var matches = hostDomainAndPortRegex.exec(url);\n if (matches) {\n var hostDomainAndPort = matches[1];\n var actualPath = matches[3];\n return hostDomainAndPort + normalizePath(actualPath);\n }\n return normalizePath(url);\n }\n\n export var pathNormalizeRegExp = /\\//g;\n\n export function normalizePath(path: string): string {\n path = switchToForwardSlashes(path);\n var startedWithSep = path.charAt(0) === \"/\";\n var parts = this.getPathComponents(path);\n for (var i = 0; i < parts.length; i++) {\n if (parts[i] === \".\" || parts[i] === \"\") {\n parts.splice(i, 1);\n i--;\n }\n if (i > 0 && parts[i] === \"..\" && parts[i - 1] !== \"..\") {\n parts.splice(i - 1, 2);\n i -= 2;\n }\n }\n return (startedWithSep ? \"/\" : \"\") + parts.join(\"/\");\n }\n\n export function normalizeImportPath(path: string): string {\n return normalizePath(path);\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n /// Compiler settings\n\n export class StyleSettings {\n // bitwise operations not permitted\n public bitwise = false; \n // disallow non-block statements as bodies of compound statements\n public blockInCompoundStmt = false;\n // disallow == and !=\n public eqeqeq = false;\n // require body of for in loop to start with a filter\n public forin = false;\n // empty blocks permitted\n public emptyBlocks = true;\n // require result of new expression to be used (no new just for side-effects)\n public newMustBeUsed = false;\n // require semicolons to terminate statements\n public requireSemi = false;\n // no top-level assignment in conditionals if (a=b) { ...\n public assignmentInCond = false;\n // no == null or != null\n public eqnull = false;\n // permit eval\n public evalOK = true;\n // permit var use if decl in inner scope as in if (c) { var v=10; } v=11;\n public innerScopeDeclEscape = true;\n // permit functions in loops\n public funcInLoop = true;\n // permit re-declaration of local variable \n public reDeclareLocal = true;\n // permit obj['x'] in addition to obj.x\n public literalSubscript = true;\n // flag implicit 'any'\n public implicitAny = false;\n\n public setOption(opt: string, val: bool): bool {\n var optExists = this[opt];\n if (optExists !== undefined) {\n this[opt] = val;\n return true;\n }\n else {\n return false;\n }\n }\n \n public parseOptions(str: string) {\n var opts=str.split(\";\");\n for (var i = 0, len = opts.length; i < len; i++) {\n var opt = opts[i];\n var val = true;\n var colonIndex=opt.lastIndexOf(\":\");\n if (colonIndex >= 0) {\n var valStr = opt.substring(colonIndex+1);\n opt = opt.substring(0, colonIndex);\n if (valStr == \"off\") {\n val = false;\n }\n }\n if (!this.setOption(opt, val)) {\n return false;\n }\n }\n return true;\n }\n }\n \n export class CompilationSettings {\n public styleSettings = new StyleSettings();\n public propagateConstants = false;\n public minWhitespace = false;\n public parseOnly = false;\n public errorRecovery = false;\n public emitComments = false;\n public watch = false;\n public exec = false;\n public resolve = true;\n public controlFlow = false;\n public printControlFlow = false;\n public controlFlowUseDef = false;\n public errorOnWith = true;\n public preprocess = true;\n public canCallDefinitionSignature = false;\n\n public inferPropertiesFromThisAssignment = false;\n public useDefaultLib = true;\n\n public codeGenTarget = CodeGenTarget.ES3;\n public moduleGenTarget = ModuleGenTarget.Synchronous;\n // --out option passed. \n // Default is the \"\" which leads to multiple files generated next to the.ts files\n public outputOption: string = \"\";\n public mapSourceFiles = false;\n public generateDeclarationFiles = false;\n\n public useCaseSensitiveFileResolution = false;\n\n public setStyleOptions(str: string) {\n this.styleSettings.parseOptions(str);\n }\n }\n\n ///\n /// Preprocessing\n ///\n export interface IPreProcessedFileInfo {\n settings: CompilationSettings;\n referencedFiles: IFileReference[];\n importedFiles: IFileReference[];\n isLibFile: bool;\n }\n\n function getFileReferenceFromReferencePath(comment: string): IFileReference {\n var referencesRegEx = /^(\\/\\/\\/\\s*<reference\\s+path=)('|\")(.+?)\\2\\s*(static=('|\")(.+?)\\2\\s*)*\\/>/gim;\n var match = referencesRegEx.exec(comment);\n\n if (match) {\n var path: string = normalizePath(match[3]);\n var adjustedPath = normalizePath(path);\n \n var isResident = match.length >= 7 && match[6] == \"true\";\n if (isResident) {\n CompilerDiagnostics.debugPrint(path + \" is resident\");\n }\n return { minChar: 0, limChar: 0, path: switchToForwardSlashes(adjustedPath), isResident: isResident };\n }\n else {\n return null;\n }\n }\n\n // used in the parser, but kept here in case we want to reintegrate it with preprocessing\n export function getAdditionalDependencyPath(comment: string): string {\n var amdDependencyRegEx = /^(\\/\\/\\/\\s*<amd-dependency\\s+path=)('|\")(.+?)\\2\\s*(static=('|\")(.+?)\\2\\s*)*\\/>/gim;\n var match = amdDependencyRegEx.exec(comment);\n\n if (match) {\n var path: string = match[3];\n return path;\n }\n else {\n return null;\n }\n }\n\n export function getImplicitImport(comment: string): bool {\n var implicitImportRegEx = /^(\\/\\/\\/\\s*<implicit-import\\s*)*\\/>/gim;\n var match = implicitImportRegEx.exec(comment);\n\n if (match) {\n return true;\n }\n \n return false;\n }\n\n export function getStyleSettings(comment: string, styleSettings: StyleSettings) {\n var styleRegEx = /^(\\/\\/\\/\\s*<style\\s+)(([a-zA-Z])+=('|\").+('|\"))\\s*\\/>/gim;\n\n var settings = styleRegEx.exec(comment);\n\n if (settings) {\n var settingsRegEx = /^([a-zA-Z]+=['\"]on['|\"])/gim;\n settings = settingsRegEx.exec(settings[2]);\n \n if (settings) {\n for (var i = 0; i < settings.length; i++) {\n var setting = (<string>settings[i]).split(\"=\");\n var on = \"\\\"on\\\"\";\n\n switch (setting[0]) {\n case \"blockInCompoundStmt\": styleSettings.blockInCompoundStmt = setting[1] == on; break;\n case \"eqeqeq\": styleSettings.eqeqeq = setting[1] == on; break;\n case \"forin\": styleSettings.forin = setting[1] == on; break;\n case \"emptyBlocks\": styleSettings.emptyBlocks = setting[1] == on; break;\n case \"newMustBeUsed\": styleSettings.newMustBeUsed = setting[1] == on; break;\n case \"requireSemi\": styleSettings.requireSemi = setting[1] == on; break;\n case \"assignmentInCond\": styleSettings.assignmentInCond = setting[1] == on; break;\n case \"eqnull\": styleSettings.eqnull = setting[1] == on; break;\n case \"evalOK\": styleSettings.evalOK = setting[1] == on; break;\n case \"innerScopeDeclEscape\": styleSettings.innerScopeDeclEscape = setting[1] == on; break;\n case \"funcInLoop\": styleSettings.funcInLoop = setting[1] == on; break;\n case \"reDeclareLocal\": styleSettings.reDeclareLocal = setting[1] == on; break;\n case \"literalSubscript\": styleSettings.literalSubscript = setting[1] == on; break;\n case \"implicitAny\": styleSettings.implicitAny = setting[1] == on; break; \n }\n }\n }\n }\n }\n\n export function getReferencedFiles(sourceText: ISourceText): IFileReference[] {\n var preProcessInfo = preProcessFile(sourceText, null, false);\n return preProcessInfo.referencedFiles;\n }\n\n export function preProcessFile(sourceText: ISourceText, options=new CompilationSettings(), readImportFiles? = true): IPreProcessedFileInfo {\n var scanner = new Scanner();\n scanner.resetComments();\n scanner.setSourceText(sourceText, LexMode.File);\n\n var tok: Token = scanner.scan();\n var comments: CommentToken[] = [];\n var comment: CommentToken = null;\n var leftCurlies: Token[] = [];\n\n var settings: CompilationSettings = options;\n var referencedFiles: IFileReference[] = [];\n var importedFiles: IFileReference[] = [];\n var isLibFile: bool = false;\n\n // only search out dynamic mods\n // if you find a dynamic mod, ignore every other mod inside, until you balance rcurlies\n\n while (tok.tokenId != TokenID.EndOfFile) {\n\n if (readImportFiles && tok.tokenId == TokenID.Import) {\n\n tok = scanner.scan();\n\n if (tok.tokenId == TokenID.Identifier || convertTokToID(tok, false)) {\n tok = scanner.scan();\n\n if (tok.tokenId == TokenID.Equals) {\n tok = scanner.scan();\n\n if (tok.tokenId == TokenID.Module) {\n tok = scanner.scan();\n if (tok.tokenId == TokenID.OpenParen) {\n tok = scanner.scan();\n\n // import foo = module(\"foo\")\n if (tok.tokenId == TokenID.StringLiteral) {\n var ref = { minChar: scanner.startPos, limChar: scanner.pos, path: stripQuotes(switchToForwardSlashes(tok.getText())), isResident: false };\n importedFiles.push(ref);\n }\n }\n }\n }\n }\n }\n\n if (tok.tokenId == TokenID.OpenBrace) {\n leftCurlies.push(tok);\n }\n\n if (tok.tokenId == TokenID.CloseBrace) {\n leftCurlies.pop();\n }\n\n tok = scanner.scan();\n }\n\n // deal with comment references, amd dependencies and style settings\n // REVIEW: We could potentially do this inline with the above, if we\n // set Scanner::scanComments to 'true'\n comments = scanner.getComments();\n\n for (var iComment = 0; iComment < comments.length; iComment++) {\n comment = comments[iComment];\n \n if (!comment.isBlock) {\n var referencedCode = getFileReferenceFromReferencePath(comment.getText());\n if (referencedCode) {\n referencedCode.minChar = comment.startPos;\n referencedCode.limChar = referencedCode.minChar + comment.value.length;\n referencedFiles.push(referencedCode);\n }\n\n if (settings) {\n getStyleSettings(comment.getText(), settings.styleSettings);\n\n // is it a lib file?\n var isNoLibRegex = /^(\\/\\/\\/\\s*<reference\\s+no-default-lib=)('|\")(.+?)\\2\\s*\\/>/gim;\n var isNoLibMatch: any = isNoLibRegex.exec(comment.getText());\n if (isNoLibMatch) {\n isLibFile = (isNoLibMatch[3] == \"true\");\n }\n }\n }\n }\n\n return { settings: settings, referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isLibFile };\n }\n\n} // Tools//\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n // TODO: refactor indent logic for use in emit\n export class PrintContext {\n public builder = \"\";\n public indent1 = \" \";\n public indentStrings: string[] = [];\n public indentAmt = 0;\n\n constructor (public outfile: ITextWriter, public parser: Parser) {\n }\n\n public increaseIndent() {\n this.indentAmt++;\n }\n\n public decreaseIndent() {\n this.indentAmt--;\n }\n\n public startLine() {\n if (this.builder.length > 0) {\n CompilerDiagnostics.Alert(this.builder);\n }\n var indentString = this.indentStrings[this.indentAmt];\n if (indentString === undefined) {\n indentString = \"\";\n for (var i = 0; i < this.indentAmt; i++) {\n indentString += this.indent1;\n }\n this.indentStrings[this.indentAmt] = indentString;\n }\n this.builder += indentString;\n }\n\n public write(s) {\n this.builder += s;\n }\n\n public writeLine(s) {\n this.builder += s;\n this.outfile.WriteLine(this.builder);\n this.builder = \"\";\n }\n\n }\n\n export function prePrintAST(ast: AST, parent: AST, walker: IAstWalker) {\n var pc: PrintContext = <PrintContext>walker.state;\n\n ast.print(pc);\n pc.increaseIndent();\n return ast;\n }\n\n\n export function postPrintAST(ast: AST, parent: AST, walker: IAstWalker) {\n var pc: PrintContext = <PrintContext>walker.state;\n pc.decreaseIndent();\n return ast;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export interface IResolvedFile {\n content: string;\n path: string;\n }\n\n /// This class acts as a convenience class to store path and content information in places\n /// where we need an ISourceText object\n export class SourceUnit implements ISourceText, IResolvedFile {\n public referencedFiles: IFileReference[] = null;\n constructor(public path: string, public content: string) {\n }\n\n public getText(start: number, end: number): string { return this.content.substring(start, end); }\n public getLength(): number { return this.content.length; }\n }\n\n export interface IFileReference {\n minChar: number;\n limChar: number;\n path: string;\n isResident: bool;\n }\n\n /// Limited API for file system manipulation\n export interface IFileSystemObject {\n resolvePath(path: string): string;\n readFile(path: string): string;\n findFile(rootPath: string, partialFilePath: string): IResolvedFile;\n dirName(path: string): string;\n }\n\n export class CompilationEnvironment {\n constructor (public compilationSettings: CompilationSettings, public ioHost: IFileSystemObject) { }\n public residentCode: SourceUnit[] = [];\n public code: SourceUnit[] = [];\n }\n\n export interface IResolutionDispatcher {\n postResolutionError(errorFile: string, errorMessage: string, errorObject: any): void;\n postResolution(path: string, source: ISourceText): void;\n }\n\n export interface ICodeResolver {\n resolveCode(referencePath: string, rootPath: string, performSearch:bool, state: IResolutionDispatcher): void;\n }\n\n export interface IResolverHost {\n resolveCompilationEnvironment(preEnvironment: CompilationEnvironment, resolver: ICodeResolver, traceDependencies: bool): CompilationEnvironment;\n }\n\n export class CodeResolver implements TypeScript.ICodeResolver {\n public visited: any = { };\n\n constructor (public environment: CompilationEnvironment) { }\n\n public resolveCode(referencePath: string, parentPath: string, performSearch: bool, resolutionDispatcher: TypeScript.IResolutionDispatcher): void {\n \n var resolvedFile: IResolvedFile = { content: null, path: referencePath };\n \n var ioHost = this.environment.ioHost;\n \n // If the path is relative, normalize it, based on the root\n var isRelativePath = TypeScript.isRelative(referencePath);\n var isRootedPath = isRelativePath ? false : isRooted(referencePath);\n var normalizedPath: string = \n isRelativePath ? ioHost.resolvePath(parentPath + \"/\" + referencePath) : \n // we only follow the second clause if the path is a non-rooted triple-slash reference path\n (isRootedPath || !parentPath || performSearch ? referencePath : parentPath + \"/\" + referencePath);\n\n // We use +=.ts to make sure we don't accidentally pick up \".js\" files or the like\n if (!isSTRFile(normalizedPath) && !isTSFile(normalizedPath)) {\n normalizedPath += \".ts\"; //changePathToSTR(normalizedPath);\n }\n\n normalizedPath = switchToForwardSlashes(stripQuotes(normalizedPath));\n var absoluteModuleID = this.environment.compilationSettings.useCaseSensitiveFileResolution ? normalizedPath : normalizedPath.toLocaleUpperCase();\n // read the file contents - if it doesn't exist, trigger a resolution error\n if (!this.visited[absoluteModuleID]) {\n\n // if the path is relative, or came from a reference tag, we don't perform a search\n if (isRelativePath || isRootedPath || !performSearch) {\n try {\n CompilerDiagnostics.debugPrint(\" Reading code from \" + normalizedPath);\n \n // Look for the .ts file first - if not present, use the .ts, the .d.str and the .d.ts\n try {\n resolvedFile.content = ioHost.readFile(normalizedPath);\n }\n catch (err) {\n try {\n if (isSTRFile(normalizedPath)) {\n normalizedPath = changePathToTS(normalizedPath);\n }\n else if (isTSFile(normalizedPath)) {\n normalizedPath = changePathToSTR(normalizedPath);\n }\n CompilerDiagnostics.debugPrint(\" Reading code from \" + normalizedPath);\n resolvedFile.content = ioHost.readFile(normalizedPath);\n }\n catch (err) {\n normalizedPath = changePathToDSTR(normalizedPath);\n CompilerDiagnostics.debugPrint(\" Reading code from \" + normalizedPath);\n\n try {\n resolvedFile.content = ioHost.readFile(normalizedPath);\n }\n catch (err) {\n normalizedPath = changePathToDTS(normalizedPath);\n CompilerDiagnostics.debugPrint(\" Reading code from \" + normalizedPath);\n resolvedFile.content = ioHost.readFile(normalizedPath);\n }\n }\n }\n CompilerDiagnostics.debugPrint(\" Found code at \" + normalizedPath);\n\n resolvedFile.path = normalizedPath;\n this.visited[absoluteModuleID] = true;\n }\n catch (err) {\n CompilerDiagnostics.debugPrint(\" Did not find code for \" + referencePath);\n }\n }\n else {\n\n // if the path is non-relative, we should attempt to search on the relative path\n resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n\n if (!resolvedFile) {\n if (isSTRFile(normalizedPath)) {\n normalizedPath = changePathToTS(normalizedPath);\n }\n else if (isTSFile(normalizedPath)) {\n normalizedPath = changePathToSTR(normalizedPath);\n }\n resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n }\n\n if (!resolvedFile) {\n normalizedPath = changePathToDTS(normalizedPath);\n resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n if (!resolvedFile) {\n normalizedPath = changePathToDSTR(normalizedPath);\n resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n }\n }\n\n if (resolvedFile) {\n resolvedFile.path = switchToForwardSlashes(TypeScript.stripQuotes(resolvedFile.path));\n CompilerDiagnostics.debugPrint(referencePath + \" resolved to: \" + resolvedFile.path);\n resolvedFile.content = resolvedFile.content;\n this.visited[absoluteModuleID] = true;\n }\n else {\n CompilerDiagnostics.debugPrint(\"Could not find \" + referencePath);\n }\n }\n\n if (resolvedFile && resolvedFile.content != null) {\n // preprocess the file, to gather dependencies\n var rootDir = ioHost.dirName(resolvedFile.path);\n var sourceUnit = new SourceUnit(resolvedFile.path, resolvedFile.content);\n var preProcessedFileInfo = preProcessFile(sourceUnit, this.environment.compilationSettings);\n sourceUnit.referencedFiles = preProcessedFileInfo.referencedFiles;\n\n // resolve explicit references\n for (var i = 0; i < preProcessedFileInfo.referencedFiles.length; i++) {\n var referencedFile = preProcessedFileInfo.referencedFiles[i];\n var normalizedPath = isRooted(referencedFile.path) ? referencedFile.path : rootDir + \"/\" + referencedFile.path;\n normalizedPath = ioHost.resolvePath(normalizedPath);\n if (referencePath == normalizedPath) {\n resolutionDispatcher.postResolutionError(normalizedPath, \"File contains reference to itself\", null);\n continue;\n }\n this.resolveCode(referencedFile.path, rootDir, false, resolutionDispatcher);\n }\n \n // resolve imports\n for (var i = 0; i < preProcessedFileInfo.importedFiles.length; i++) {\n this.resolveCode(preProcessedFileInfo.importedFiles[i].path, rootDir, true, resolutionDispatcher);\n }\n\n // add the file to the appropriate code list\n resolutionDispatcher.postResolution(sourceUnit.path, sourceUnit);\n }\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export var LexEOF = (-1);\n\n export var LexCodeNWL = 0x0A;\n export var LexCodeRET = 0x0D;\n export var LexCodeLS = 0x2028;\n export var LexCodePS = 0x2029;\n export var LexCodeTAB = 0x09;\n export var LexCodeVTAB = 0x0B;\n export var LexCode_e = 'e'.charCodeAt(0);\n export var LexCode_E = 'E'.charCodeAt(0);\n export var LexCode_x = 'x'.charCodeAt(0);\n export var LexCode_X = 'X'.charCodeAt(0);\n export var LexCode_a = 'a'.charCodeAt(0);\n export var LexCode_A = 'A'.charCodeAt(0);\n export var LexCode_f = 'f'.charCodeAt(0);\n export var LexCode_F = 'F'.charCodeAt(0);\n\n export var LexCode_g = 'g'.charCodeAt(0);\n export var LexCode_m = 'm'.charCodeAt(0);\n export var LexCode_i = 'i'.charCodeAt(0);\n\n export var LexCode_u = 'u'.charCodeAt(0);\n\n export var LexCode_0 = '0'.charCodeAt(0);\n export var LexCode_9 = '9'.charCodeAt(0);\n export var LexCode_8 = '8'.charCodeAt(0);\n export var LexCode_7 = '7'.charCodeAt(0);\n\n export var LexCodeBSL = '\\\\'.charCodeAt(0);\n export var LexCodeSHP = '#'.charCodeAt(0);\n export var LexCodeBNG = '!'.charCodeAt(0);\n export var LexCodeQUO = '\"'.charCodeAt(0);\n export var LexCodeAPO = '\\''.charCodeAt(0);\n export var LexCodePCT = '%'.charCodeAt(0);\n export var LexCodeAMP = '&'.charCodeAt(0);\n export var LexCodeLPR = '('.charCodeAt(0);\n export var LexCodeRPR = ')'.charCodeAt(0);\n export var LexCodePLS = '+'.charCodeAt(0);\n export var LexCodeMIN = '-'.charCodeAt(0);\n export var LexCodeMUL = '*'.charCodeAt(0);\n export var LexCodeSLH = '/'.charCodeAt(0);\n export var LexCodeXOR = '^'.charCodeAt(0);\n export var LexCodeCMA = ','.charCodeAt(0);\n export var LexCodeDOT = '.'.charCodeAt(0);\n export var LexCodeLT = '<'.charCodeAt(0);\n export var LexCodeEQ = '='.charCodeAt(0);\n export var LexCodeGT = '>'.charCodeAt(0);\n export var LexCodeQUE = '?'.charCodeAt(0);\n export var LexCodeLBR = '['.charCodeAt(0);\n export var LexCodeRBR = ']'.charCodeAt(0);\n export var LexCodeUSC = '_'.charCodeAt(0);\n export var LexCodeLC = '{'.charCodeAt(0);\n export var LexCodeRC = '}'.charCodeAt(0);\n export var LexCodeBAR = '|'.charCodeAt(0);\n export var LexCodeTIL = '~'.charCodeAt(0);\n export var LexCodeCOL = ':'.charCodeAt(0);\n export var LexCodeSMC = ';'.charCodeAt(0);\n export var LexCodeUnderscore = '_'.charCodeAt(0);\n export var LexCodeDollar = '$'.charCodeAt(0);\n export var LexCodeSpace = 32;\n export var LexCodeAtSign = '@'.charCodeAt(0);\n export var LexCodeASCIIChars = 128;\n\n export var LexKeywordTable = undefined;\n // TODO: use new Token[128];\n var autoToken: Token[] = new Array(LexCodeASCIIChars);\n var lexIdStartTable: bool[] = new Array(LexCodeASCIIChars);\n\n // Unicode range maps\n // REVIEW: These range maps have been extracted from the Unicode specifications, they might be missing values, and/or include \n // incorrect ranges. but for the most they seem to be correct. A more accurate and thorough review is needed.\n\n /*\n As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers\n IdentifierStart :: Can contain Unicode 3.0.0 categories Uppercase letter (Lu), Lowercase letter (Ll), Titlecase letter (Lt), Modifier letter (Lm), Other letter (Lo), or Letter number (Nl).\n IdentifierPart :: Can contain IdentifierStart + Unicode 3.0.0 categories Non-spacing mark (Mn), Combining spacing mark (Mc), Decimal number (Nd), or Connector punctuation (Pc).\n \n Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at:\n http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt\n */\n var unicodeES3IdStart = [\n 170, 170,181, 181,186, 186,192, 214,216, 246,248, 543,546, 563,592, 685,688, 696,699, 705,720, 721,736, 740,750, 750,890, 890,902, 902,904, 906,908, 908,910, 929,931, 974,976, 983,986, 1011,1024, 1153,1164, 1220,1223, 1224,1227, 1228,1232, 1269,1272, 1273,1329, 1366,1369, 1369,1377, 1415,1488, 1514,\n 1520, 1522,1569, 1594,1600, 1610,1649, 1747,1749, 1749,1765, 1766,1786, 1788,1808, 1808,1810, 1836,1920, 1957,2309, 2361,2365, 2365,2384, 2384,2392, 2401,2437, 2444,2447, 2448,2451, 2472,2474, 2480,2482, 2482,2486, 2489,2524, 2525,2527, 2529,2544, 2545,2565, 2570,2575, 2576,2579, 2600,2602, 2608,2610, 2611,\n 2613, 2614,2616, 2617,2649, 2652,2654, 2654,2674, 2676,2693, 2699,2701, 2701,2703, 2705,2707, 2728,2730, 2736,2738, 2739,2741, 2745,2749, 2749,2768, 2768,2784, 2784,2821, 2828,2831, 2832,2835, 2856,2858, 2864,2866, 2867,2870, 2873,2877, 2877,2908, 2909,2911, 2913,2949, 2954,2958, 2960,2962, 2965,2969, 2970,\n 2972, 2972,2974, 2975,2979, 2980,2984, 2986,2990, 2997,2999, 3001,3077, 3084,3086, 3088,3090, 3112,3114, 3123,3125, 3129,3168, 3169,3205, 3212,3214, 3216,3218, 3240,3242, 3251,3253, 3257,3294, 3294,3296, 3297,3333, 3340,3342, 3344,3346, 3368,3370, 3385,3424, 3425,3461, 3478,3482, 3505,3507, 3515,3517, 3517,\n 3520, 3526,3585, 3632,3634, 3635,3648, 3654,3713, 3714,3716, 3716,3719, 3720,3722, 3722,3725, 3725,3732, 3735,3737, 3743,3745, 3747,3749, 3749,3751, 3751,3754, 3755,3757, 3760,3762, 3763,3773, 3773,3776, 3780,3782, 3782,3804, 3805,3840, 3840,3904, 3911,3913, 3946,3976, 3979,4096, 4129,4131, 4135,4137, 4138,\n 4176, 4181,4256, 4293,4304, 4342,4352, 4441,4447, 4514,4520, 4601,4608, 4614,4616, 4678,4680, 4680,4682, 4685,4688, 4694,4696, 4696,4698, 4701,4704, 4742,4744, 4744,4746, 4749,4752, 4782,4784, 4784,4786, 4789,4792, 4798,4800, 4800,4802, 4805,4808, 4814,4816, 4822,4824, 4846,4848, 4878,4880, 4880,4882, 4885,\n 4888, 4894,4896, 4934,4936, 4954,5024, 5108,5121, 5740,5743, 5750,5761, 5786,5792, 5866,6016, 6067,6176, 6263,6272, 6312,7680, 7835,7840, 7929,7936, 7957,7960, 7965,7968, 8005,8008, 8013,8016, 8023,8025, 8025,8027, 8027,8029, 8029,8031, 8061,8064, 8116,8118, 8124,8126, 8126,8130, 8132,8134, 8140,8144, 8147,\n 8150, 8155,8160, 8172,8178, 8180,8182, 8188,8319, 8319,8450, 8450,8455, 8455,8458, 8467,8469, 8469,8473, 8477,8484, 8484,8486, 8486,8488, 8488,8490, 8493,8495, 8497,8499, 8505,8544, 8579,12293, 12295,12321, 12329,12337, 12341,12344, 12346,12353, 12436,12445, 12446,12449, 12538,12540, 12542,12549, 12588,\n 12593, 12686,12704, 12727,13312, 13312,19893, 19893,19968, 19968,40869, 40869,40960, 42124,44032, 44032,55203, 55203,63744, 64045,64256, 64262,64275, 64279,64285, 64285,64287, 64296,64298, 64310,64312, 64316,64318, 64318,64320, 64321,64323, 64324,64326, 64433,64467, 64829,64848, 64911,64914, 64967,\n 65008, 65019,65136, 65138,65140, 65140,65142, 65276,65313, 65338,65345, 65370,65382, 65470,65474, 65479,65482, 65487,65490, 65495,65498, 65500\n ];\n\n var unicodeES3IdCont = [\n 768, 846,864, 866,1155, 1158,1425, 1441,1443, 1465,1467, 1469,1471, 1471,1473, 1474,1476, 1476,1611, 1621,1632, 1641,1648, 1648,1750, 1756,1759, 1764,1767, 1768,1770, 1773,1776, 1785,1809, 1809,1840, 1866,1958, 1968,2305, 2307,2364, 2364,2366, 2381,2385, 2388,2402, 2403,2406, 2415,2433, 2435,2492, 2492,\n 2494, 2500,2503, 2504,2507, 2509,2519, 2519,2530, 2531,2534, 2543,2562, 2562,2620, 2620,2622, 2626,2631, 2632,2635, 2637,2662, 2673,2689, 2691,2748, 2748,2750, 2757,2759, 2761,2763, 2765,2790, 2799,2817, 2819,2876, 2876,2878, 2883,2887, 2888,2891, 2893,2902, 2903,2918, 2927,2946, 2947,3006, 3010,3014, 3016,\n 3018, 3021,3031, 3031,3047, 3055,3073, 3075,3134, 3140,3142, 3144,3146, 3149,3157, 3158,3174, 3183,3202, 3203,3262, 3268,3270, 3272,3274, 3277,3285, 3286,3302, 3311,3330, 3331,3390, 3395,3398, 3400,3402, 3405,3415, 3415,3430, 3439,3458, 3459,3530, 3530,3535, 3540,3542, 3542,3544, 3551,3570, 3571,3633, 3633,\n 3636, 3642,3655, 3662,3664, 3673,3761, 3761,3764, 3769,3771, 3772,3784, 3789,3792, 3801,3864, 3865,3872, 3881,3893, 3893,3895, 3895,3897, 3897,3902, 3903,3953, 3972,3974, 3975,3984, 3991,3993, 4028,4038, 4038,4140, 4146,4150, 4153,4160, 4169,4182, 4185,4969, 4977,6068, 6099,6112, 6121,6160, 6169,6313, 6313,\n 8255, 8256,8400, 8412,8417, 8417,12330, 12335,12441, 12442,12539, 12539,64286, 64286,65056, 65059,65075, 65076,65101, 65103,65296, 65305,65343, 65343,65381, 65381\n ];\n\n\n /*\n As per ECMAScript Language Specification 5th Edition, Section 7.6: Identifier Names and Identifiers\n IdentifierStart :: Can contain Unicode 6.2 categories Uppercase letter (Lu), Lowercase letter (Ll), Titlecase letter (Lt), Modifier letter (Lm), Other letter (Lo), or Letter number (Nl).\n IdentifierPart :: Can contain IdentifierStart + Unicode 6.2 categories Non-spacing mark (Mn), Combining spacing mark (Mc), Decimal number (Nd), Connector punctuation (Pc), <ZWNJ>, or <ZWJ>.\n \n Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at:\n http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt\n */\n var unicodeES5IdStart = [\n 170, 170,181, 181,186, 186,192, 214,216, 246,248, 705,710, 721,736, 740,748, 748,750, 750,880, 884,886, 887,890, 893,902, 902,904, 906,908, 908,910, 929,931, 1013,1015, 1153,1162, 1319,1329, 1366,1369, 1369,1377, 1415,1488, 1514,1520, 1522,1568, 1610,1646, 1647,1649, 1747,1749, 1749,1765, 1766,1774, 1775,\n 1786, 1788,1791, 1791,1808, 1808,1810, 1839,1869, 1957,1969, 1969,1994, 2026,2036, 2037,2042, 2042,2048, 2069,2074, 2074,2084, 2084,2088, 2088,2112, 2136,2208, 2208,2210, 2220,2308, 2361,2365, 2365,2384, 2384,2392, 2401,2417, 2423,2425, 2431,2437, 2444,2447, 2448,2451, 2472,2474, 2480,2482, 2482,2486, 2489,\n 2493, 2493,2510, 2510,2524, 2525,2527, 2529,2544, 2545,2565, 2570,2575, 2576,2579, 2600,2602, 2608,2610, 2611,2613, 2614,2616, 2617,2649, 2652,2654, 2654,2674, 2676,2693, 2701,2703, 2705,2707, 2728,2730, 2736,2738, 2739,2741, 2745,2749, 2749,2768, 2768,2784, 2785,2821, 2828,2831, 2832,2835, 2856,2858, 2864,\n 2866, 2867,2869, 2873,2877, 2877,2908, 2909,2911, 2913,2929, 2929,2947, 2947,2949, 2954,2958, 2960,2962, 2965,2969, 2970,2972, 2972,2974, 2975,2979, 2980,2984, 2986,2990, 3001,3024, 3024,3077, 3084,3086, 3088,3090, 3112,3114, 3123,3125, 3129,3133, 3133,3160, 3161,3168, 3169,3205, 3212,3214, 3216,3218, 3240,\n 3242, 3251,3253, 3257,3261, 3261,3294, 3294,3296, 3297,3313, 3314,3333, 3340,3342, 3344,3346, 3386,3389, 3389,3406, 3406,3424, 3425,3450, 3455,3461, 3478,3482, 3505,3507, 3515,3517, 3517,3520, 3526,3585, 3632,3634, 3635,3648, 3654,3713, 3714,3716, 3716,3719, 3720,3722, 3722,3725, 3725,3732, 3735,3737, 3743,\n 3745, 3747,3749, 3749,3751, 3751,3754, 3755,3757, 3760,3762, 3763,3773, 3773,3776, 3780,3782, 3782,3804, 3807,3840, 3840,3904, 3911,3913, 3948,3976, 3980,4096, 4138,4159, 4159,4176, 4181,4186, 4189,4193, 4193,4197, 4198,4206, 4208,4213, 4225,4238, 4238,4256, 4293,4295, 4295,4301, 4301,4304, 4346,4348, 4680,\n 4682, 4685,4688, 4694,4696, 4696,4698, 4701,4704, 4744,4746, 4749,4752, 4784,4786, 4789,4792, 4798,4800, 4800,4802, 4805,4808, 4822,4824, 4880,4882, 4885,4888, 4954,4992, 5007,5024, 5108,5121, 5740,5743, 5759,5761, 5786,5792, 5866,5870, 5872,5888, 5900,5902, 5905,5920, 5937,5952, 5969,5984, 5996,5998, 6000,\n 6016, 6067,6103, 6103,6108, 6108,6176, 6263,6272, 6312,6314, 6314,6320, 6389,6400, 6428,6480, 6509,6512, 6516,6528, 6571,6593, 6599,6656, 6678,6688, 6740,6823, 6823,6917, 6963,6981, 6987,7043, 7072,7086, 7087,7098, 7141,7168, 7203,7245, 7247,7258, 7293,7401, 7404,7406, 7409,7413, 7414,7424, 7615,7680, 7957,\n 7960, 7965,7968, 8005,8008, 8013,8016, 8023,8025, 8025,8027, 8027,8029, 8029,8031, 8061,8064, 8116,8118, 8124,8126, 8126,8130, 8132,8134, 8140,8144, 8147,8150, 8155,8160, 8172,8178, 8180,8182, 8188,8305, 8305,8319, 8319,8336, 8348,8450, 8450,8455, 8455,8458, 8467,8469, 8469,8473, 8477,8484, 8484,8486, 8486,\n 8488, 8488,8490, 8493,8495, 8505,8508, 8511,8517, 8521,8526, 8526,8544, 8584,11264, 11310,11312, 11358,11360, 11492,11499, 11502,11506, 11507,11520, 11557,11559, 11559,11565, 11565,11568, 11623,11631, 11631,11648, 11670,11680, 11686,11688, 11694,11696, 11702,11704, 11710,11712, 11718,11720, 11726,\n 11728, 11734,11736, 11742,11823, 11823,12293, 12295,12321, 12329,12337, 12341,12344, 12348,12353, 12438,12445, 12447,12449, 12538,12540, 12543,12549, 12589,12593, 12686,12704, 12730,12784, 12799,13312, 13312,19893, 19893,19968, 19968,40908, 40908,40960, 42124,42192, 42237,42240, 42508,42512, 42527,\n 42538, 42539,42560, 42606,42623, 42647,42656, 42735,42775, 42783,42786, 42888,42891, 42894,42896, 42899,42912, 42922,43000, 43009,43011, 43013,43015, 43018,43020, 43042,43072, 43123,43138, 43187,43250, 43255,43259, 43259,43274, 43301,43312, 43334,43360, 43388,43396, 43442,43471, 43471,43520, 43560,\n 43584, 43586,43588, 43595,43616, 43638,43642, 43642,43648, 43695,43697, 43697,43701, 43702,43705, 43709,43712, 43712,43714, 43714,43739, 43741,43744, 43754,43762, 43764,43777, 43782,43785, 43790,43793, 43798,43808, 43814,43816, 43822,43968, 44002,44032, 44032,55203, 55203,55216, 55238,55243, 55291,\n 63744, 64109,64112, 64217,64256, 64262,64275, 64279,64285, 64285,64287, 64296,64298, 64310,64312, 64316,64318, 64318,64320, 64321,64323, 64324,64326, 64433,64467, 64829,64848, 64911,64914, 64967,65008, 65019,65136, 65140,65142, 65276,65313, 65338,65345, 65370,65382, 65470,65474, 65479,65482, 65487,\n 65490, 65495,65498, 65500\n ];\n\n var unicodeES5IdCont = [\n 768, 879,1155, 1159,1425, 1469,1471, 1471,1473, 1474,1476, 1477,1479, 1479,1552, 1562,1611, 1641,1648, 1648,1750, 1756,1759, 1764,1767, 1768,1770, 1773,1776, 1785,1809, 1809,1840, 1866,1958, 1968,1984, 1993,2027, 2035,2070, 2073,2075, 2083,2085, 2087,2089, 2093,2137, 2139,2276, 2302,2304, 2307,2362, 2364,\n 2366, 2383,2385, 2391,2402, 2403,2406, 2415,2433, 2435,2492, 2492,2494, 2500,2503, 2504,2507, 2509,2519, 2519,2530, 2531,2534, 2543,2561, 2563,2620, 2620,2622, 2626,2631, 2632,2635, 2637,2641, 2641,2662, 2673,2677, 2677,2689, 2691,2748, 2748,2750, 2757,2759, 2761,2763, 2765,2786, 2787,2790, 2799,2817, 2819,\n 2876, 2876,2878, 2884,2887, 2888,2891, 2893,2902, 2903,2914, 2915,2918, 2927,2946, 2946,3006, 3010,3014, 3016,3018, 3021,3031, 3031,3046, 3055,3073, 3075,3134, 3140,3142, 3144,3146, 3149,3157, 3158,3170, 3171,3174, 3183,3202, 3203,3260, 3260,3262, 3268,3270, 3272,3274, 3277,3285, 3286,3298, 3299,3302, 3311,\n 3330, 3331,3390, 3396,3398, 3400,3402, 3405,3415, 3415,3426, 3427,3430, 3439,3458, 3459,3530, 3530,3535, 3540,3542, 3542,3544, 3551,3570, 3571,3633, 3633,3636, 3642,3655, 3662,3664, 3673,3761, 3761,3764, 3769,3771, 3772,3784, 3789,3792, 3801,3864, 3865,3872, 3881,3893, 3893,3895, 3895,3897, 3897,3902, 3903,\n 3953, 3972,3974, 3975,3981, 3991,3993, 4028,4038, 4038,4139, 4158,4160, 4169,4182, 4185,4190, 4192,4194, 4196,4199, 4205,4209, 4212,4226, 4237,4239, 4253,4957, 4959,5906, 5908,5938, 5940,5970, 5971,6002, 6003,6068, 6099,6109, 6109,6112, 6121,6155, 6157,6160, 6169,6313, 6313,6432, 6443,6448, 6459,6470, 6479,\n 6576, 6592,6600, 6601,6608, 6617,6679, 6683,6741, 6750,6752, 6780,6783, 6793,6800, 6809,6912, 6916,6964, 6980,6992, 7001,7019, 7027,7040, 7042,7073, 7085,7088, 7097,7142, 7155,7204, 7223,7232, 7241,7248, 7257,7376, 7378,7380, 7400,7405, 7405,7410, 7412,7616, 7654,7676, 7679,8204, 8205,8255, 8256,8276, 8276,\n 8400, 8412,8417, 8417,8421, 8432,11503, 11505,11647, 11647,11744, 11775,12330, 12335,12441, 12442,42528, 42537,42607, 42607,42612, 42621,42655, 42655,42736, 42737,43010, 43010,43014, 43014,43019, 43019,43043, 43047,43136, 43137,43188, 43204,43216, 43225,43232, 43249,43264, 43273,43302, 43309,43335, 43347,\n 43392, 43395,43443, 43456,43472, 43481,43561, 43574,43587, 43587,43596, 43597,43600, 43609,43643, 43643,43696, 43696,43698, 43700,43703, 43704,43710, 43711,43713, 43713,43755, 43759,43765, 43766,44003, 44010,44012, 44013,44016, 44025,64286, 64286,65024, 65039,65056, 65062,65075, 65076,65101, 65103,\n 65296, 65305,65343, 65343\n ];\n\n export function LexLookUpUnicodeMap(code: number, map: number[]) : bool {\n // Perform binary search in one of the unicode range maps\n var lo: number = 0;\n var hi: number = map.length;\n var mid: number;\n\n while (lo + 1 < hi)\n {\n mid = lo + (hi - lo) / 2;\n // mid has to be even to catch a range's beginning\n mid -= mid % 2;\n if (map[mid] <= code && code <= map[mid + 1])\n return true;\n if (code < map[mid])\n hi = mid;\n else\n lo = mid + 2;\n }\n return false;\n }\n\n export function LexIsUnicodeDigit(code: number): bool {\n if (codeGenTarget == CodeGenTarget.ES3) {\n return LexLookUpUnicodeMap(code, unicodeES3IdCont);\n } else {\n return LexLookUpUnicodeMap(code, unicodeES5IdCont);\n }\n }\n\n export function LexIsUnicodeIdStart(code: number): bool {\n if (codeGenTarget == CodeGenTarget.ES3) {\n return LexLookUpUnicodeMap(code, unicodeES3IdStart);\n } else {\n return LexLookUpUnicodeMap(code, unicodeES5IdStart);\n }\n }\n export function LexInitialize() {\n initializeStaticTokens();\n autoToken[LexCodeLPR] = staticTokens[TokenID.OpenParen];\n autoToken[LexCodeRPR] = staticTokens[TokenID.CloseParen];\n autoToken[LexCodeCMA] = staticTokens[TokenID.Comma];\n autoToken[LexCodeSMC] = staticTokens[TokenID.Semicolon];\n autoToken[LexCodeLBR] = staticTokens[TokenID.OpenBracket];\n autoToken[LexCodeRBR] = staticTokens[TokenID.CloseBracket];\n autoToken[LexCodeTIL] = staticTokens[TokenID.Tilde];\n autoToken[LexCodeQUE] = staticTokens[TokenID.Question];\n autoToken[LexCodeLC] = staticTokens[TokenID.OpenBrace];\n autoToken[LexCodeRC] = staticTokens[TokenID.CloseBrace];\n autoToken[LexCodeCOL] = staticTokens[TokenID.Colon];\n LexKeywordTable = new StringHashTable();\n for (var i in (<any>TokenID)._map) {\n if ((<number><any>i) <= TokenID.LimKeyword) {\n LexKeywordTable.add((<any>TokenID)._map[i].toLowerCase(), i);\n }\n }\n for (var j = 0; j < LexCodeASCIIChars; j++) {\n if (LexIsIdentifierStartChar(j)) {\n lexIdStartTable[j] = true;\n }\n else {\n lexIdStartTable[j] = false;\n }\n }\n }\n\n export function LexAdjustIndent(code, indentAmt) {\n if ((code == LexCodeLBR) || (code == LexCodeLC) || (code == LexCodeLPR)) {\n return indentAmt + 1;\n }\n else if ((code == LexCodeRBR) || (code == LexCodeRC) || (code == LexCodeRPR)) {\n return indentAmt - 1;\n }\n else return indentAmt;\n }\n\n export function LexIsIdentifierStartChar(code): bool {\n return (((code >= 97) && (code <= 122)) ||\n ((code >= 65) && (code <= 90)) ||\n (code == LexCodeDollar) ||\n (code == LexCodeUnderscore));\n }\n\n export function LexIsDigit(code): bool {\n return ((code >= 48) && (code <= 57));\n }\n\n export function LexIsIdentifierChar(code:number) {\n return lexIdStartTable[code] || LexIsDigit(code);\n }\n\n export function LexMatchingOpen(code) {\n if (code == LexCodeRBR)\n return LexCodeLBR;\n else if (code == LexCodeRC)\n return LexCodeLC;\n else if (code == LexCodeRPR)\n return LexCodeLPR;\n else return 0;\n }\n\n export enum NumberScanState {\n Start,\n InFraction,\n InEmptyFraction,\n InExponent\n }\n\n export enum LexState {\n Start,\n InMultilineComment,\n InMultilineSingleQuoteString,\n InMultilineDoubleQuoteString,\n }\n\n export enum LexMode {\n Line,\n File,\n }\n\n export enum CommentStyle {\n Line,\n Block\n }\n\n // Represent a piece of source code which can be read in multiple segments\n export interface ISourceText {\n getText(start: number, end: number): string;\n getLength(): number;\n }\n\n // Implementation on top of a contiguous string\n export class StringSourceText implements ISourceText {\n constructor (public text: string) {\n }\n\n public getText(start: number, end: number): string {\n return this.text.substring(start, end);\n }\n\n public getLength(): number {\n return this.text.length;\n }\n }\n\n export class SourceTextSegment implements ISourceTextSegment {\n constructor (public segmentStart: number,\n public segmentEnd: number,\n public segment: string) {\n }\n\n charCodeAt(index: number): number {\n return this.segment.charCodeAt(index - this.segmentStart);\n }\n\n substring(start: number, end: number): string {\n return this.segment.substring(start - this.segmentStart, end - this.segmentStart);\n }\n }\n\n export class AggerateSourceTextSegment implements ISourceTextSegment {\n\n constructor (public seg1: SourceTextSegment, public seg2: SourceTextSegment) { }\n\n public charCodeAt(index: number): number {\n if (this.seg1.segmentStart <= index && index < this.seg1.segmentEnd)\n return this.seg1.segment.charCodeAt(index - this.seg1.segmentStart);\n\n return this.seg2.segment.charCodeAt(index - this.seg2.segmentStart);\n }\n\n public substring(start: number, end: number): string {\n if (this.seg1.segmentStart <= start && end <= this.seg1.segmentEnd)\n return this.seg1.segment.substring(start - this.seg1.segmentStart, end - this.seg1.segmentStart);\n\n return this.seg2.segment.substring(start - this.seg2.segmentStart) + this.seg1.segment.substring(0, end - this.seg1.segmentStart);\n }\n }\n\n export interface ISourceTextSegment {\n charCodeAt(index: number): number;\n substring(start: number, end: number): string;\n }\n\n export class ScannerTextStream {\n static emptySegment = new SourceTextSegment(0, 0, \"\");\n public agg: AggerateSourceTextSegment;\n public len: number;\n\n constructor (public sourceText: ISourceText) {\n this.agg = new AggerateSourceTextSegment(ScannerTextStream.emptySegment, ScannerTextStream.emptySegment);\n this.len = this.sourceText.getLength();\n }\n\n public max(a: number, b: number): number {\n return a >= b ? a : b;\n }\n\n public min(a: number, b: number): number {\n return a <= b ? a : b;\n }\n\n public fetchSegment(start: number, end: number): ISourceTextSegment {\n // Common case\n if (this.agg.seg1.segmentStart <= start && end <= this.agg.seg1.segmentEnd)\n return this.agg.seg1;\n\n // Common overlap case\n if (this.agg.seg2.segmentStart <= start && end <= this.agg.seg1.segmentEnd)\n return this.agg;\n\n // if overlapping outside of fetched segment(s), fetch a new segment\n var prev = this.agg.seg1;\n\n var s = prev.segmentEnd;\n var e = max(s + 512, end); // ensure we move forward at least 512 characters or \"end\"\n e = min(e, this.len); // but don't go past the end of the source text\n\n var src = this.sourceText.getText(s, e);\n var newSeg = new SourceTextSegment(s, e, src);\n this.agg.seg2 = prev;\n this.agg.seg1 = newSeg;\n return this.agg;\n }\n\n public charCodeAt(index: number): number {\n return this.fetchSegment(index, index + 1).charCodeAt(index);\n }\n\n public substring(start: number, end: number) {\n return this.fetchSegment(start, end).substring(start, end);\n }\n }\n\n export interface IScanner {\n startPos: number;\n pos: number;\n scan(): Token;\n previousToken(): Token;\n prevLine: number;\n line: number;\n col: number;\n leftCurlyCount: number;\n rightCurlyCount: number;\n lastTokenLimChar(): number;\n lastTokenHadNewline(): bool;\n lexState: number;\n getComments(): CommentToken[];\n getCommentsForLine(line: number): CommentToken[];\n resetComments(): void;\n lineMap: number[];\n setSourceText(newSrc: ISourceText, textMode: number): void;\n setErrorHandler(reportError: (message: string) => void): void;\n seenUnicodeChar: bool;\n seenUnicodeCharInComment: bool;\n getLookAheadToken(): Token;\n }\n\n export class SavedTokens implements IScanner {\n public prevToken: Token = null;\n public curSavedToken: SavedToken = null;\n public prevSavedToken: SavedToken = null;\n public currentTokenIndex: number;\n public currentTokens: SavedToken[];\n public tokensByLine: SavedToken[][];\n public lexStateByLine: LexState[];\n private prevToken: SavedToken = null;\n public previousToken(): Token { return this.prevToken; }\n public currentToken = 0;\n public tokens = new SavedToken[];\n public startPos: number;\n public pos: number;\n public seenUnicodeChar: bool = false;\n seenUnicodeCharInComment: bool = false;\n\n public close() {\n this.currentToken = 0;\n }\n\n public addToken(tok: Token, scanner: IScanner) {\n this.tokens[this.currentToken++] = new SavedToken(tok, scanner.startPos, scanner.pos);\n }\n\n public scan(): Token {\n // TODO: curly count\n this.startLine = this.line;\n this.startPos = this.col;\n if (this.currentTokenIndex == this.currentTokens.length) {\n if (this.line < this.lineMap.length) {\n this.line++;\n this.col = 0;\n this.currentTokenIndex = 0;\n this.currentTokens = this.tokensByLine[this.line];\n }\n else {\n return staticTokens[TokenID.EndOfFile];\n }\n }\n if (this.currentTokenIndex < this.currentTokens.length) {\n this.prevToken = this.curSavedToken.tok;\n this.prevSavedToken = this.curSavedToken;\n this.curSavedToken = this.currentTokens[this.currentTokenIndex++];\n var curToken = this.curSavedToken.tok;\n this.pos = this.curSavedToken.limChar;\n this.col += (this.curSavedToken.limChar - this.curSavedToken.minChar);\n this.startPos = this.curSavedToken.minChar;\n this.prevLine = this.line;\n return curToken;\n }\n else {\n return staticTokens[TokenID.EndOfFile];\n }\n }\n public startLine: number;\n public prevLine = 1;\n public line = 1;\n public col = 0;\n public leftCurlyCount: number;\n public rightCurlyCount: number;\n\n public syncToTok(offset: number): number {\n this.line = getLineNumberFromPosition(this.lineMap, offset);\n this.currentTokenIndex = 0;\n var tmpCol = offset - this.lineMap[this.line];\n while ((this.lexStateByLine[this.line] == LexState.InMultilineComment) && (this.line > 0)) {\n this.line--;\n tmpCol = 0;\n }\n var lenMin1 = this.lineMap.length - 1;\n this.currentTokens = this.tokensByLine[this.line];\n while ((this.currentTokens.length == 0) && (this.line < lenMin1)) {\n this.line++;\n this.currentTokens = this.tokensByLine[this.line];\n tmpCol = 0;\n }\n if (this.line <= lenMin1) {\n while ((this.currentTokenIndex < this.currentTokens.length) &&\n (tmpCol > this.currentTokens[this.currentTokenIndex].limChar)) {\n this.currentTokenIndex++;\n }\n if (this.currentTokenIndex < this.currentTokens.length) {\n this.col = this.currentTokens[this.currentTokenIndex].minChar;\n return this.col + this.lineMap[this.line];\n }\n }\n return -1;\n }\n\n public lastTokenLimChar(): number {\n if (this.prevSavedToken !== null) {\n return this.prevSavedToken.limChar;\n }\n else {\n return 0;\n }\n }\n\n public lastTokenHadNewline(): bool {\n return this.prevLine != this.startLine;\n }\n\n public lexState = LexState.Start;\n\n public commentStack: CommentToken[] = new CommentToken[];\n\n public pushComment(comment: CommentToken) {\n this.commentStack.push(comment);\n }\n\n public getComments() {\n var stack = this.commentStack;\n this.commentStack = [];\n return stack;\n }\n\n public getCommentsForLine(line: number) {\n var comments: CommentToken[] = null;\n while ((this.commentStack.length > 0) && (this.commentStack[0].line == line)) {\n if (comments == null) {\n comments = [this.commentStack.shift()];\n }\n else {\n comments = comments.concat([this.commentStack.shift()]);\n }\n\n }\n return comments;\n }\n\n public resetComments() {\n this.commentStack = [];\n }\n\n public lineMap: number[] = [];\n public setSourceText(newSrc: ISourceText, textMode: number) {\n }\n public setErrorHandler(reportError: (message: string) => void ) { \n }\n public getLookAheadToken(): Token {\n throw new Error(\"Invalid operation.\");\n }\n }\n\n export class Scanner implements IScanner {\n // REVIEW: When adding new variables make sure to handle storing them in getLookAheadToken. \n // The method works by storing the state before scanning and restoring it later on, missing a member variable \n // could result in an inconsistent state.\n public prevLine = 1;\n public line = 1;\n public col = 0;\n public pos = 0;\n public startPos = 0;\n public startCol: number;\n public startLine: number;\n public src: string;\n public len = 0;\n public lineMap: number[] = [];\n \n public ch = LexEOF;\n public lexState = LexState.Start;\n public mode = LexMode.File;\n public scanComments: bool = true;\n public interveningWhitespace = false; // Was there a whitespace token between the last token and the current one?\n private interveningWhitespacePos = 0; // If yes, this contains the start position of the whitespace\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public commentStack: CommentToken[] = new CommentToken[];\n public saveScan: SavedTokens = null;\n public seenUnicodeChar: bool = false;\n seenUnicodeCharInComment: bool = false;\n\n private reportError: (message: string) =>void;\n\n constructor () {\n this.startCol = this.col;\n this.startLine = this.line; \n this.lineMap[1] = 0;\n \n if (!LexKeywordTable) {\n LexInitialize();\n } \n }\n\n private prevTok = staticTokens[TokenID.EndOfFile];\n public previousToken() { return this.prevTok; }\n\n public setSourceText(newSrc: ISourceText, textMode: number) {\n this.mode = textMode;\n this.scanComments = (this.mode === LexMode.Line);\n this.pos = 0;\n this.interveningWhitespacePos = 0;\n this.startPos = 0;\n this.line = 1;\n this.col = 0;\n this.startCol = this.col;\n this.startLine = this.line;\n this.len = 0;\n this.src = newSrc.getText(0, newSrc.getLength());\n this.len = this.src.length;\n this.lineMap = [];\n this.lineMap[1] = 0;\n this.commentStack = [];\n this.leftCurlyCount = 0;\n this.rightCurlyCount = 0;\n this.seenUnicodeChar = false;\n this.seenUnicodeCharInComment = false;\n }\n\n public setErrorHandler(reportError: (message: string) => void ) { \n this.reportError = reportError;\n }\n\n public setSaveScan(savedTokens: SavedTokens) {\n this.saveScan = savedTokens;\n }\n\n public setText(newSrc: string, textMode: number) {\n this.setSourceText(new StringSourceText(newSrc), textMode);\n }\n\n public setScanComments(value: bool) {\n this.scanComments = value;\n }\n\n public getLexState(): number {\n return this.lexState;\n }\n\n public tokenStart() {\n this.startPos = this.pos;\n this.startLine = this.line;\n this.startCol = this.col;\n this.interveningWhitespace = false;\n }\n\n public peekChar(): number {\n if (this.pos < this.len) {\n return this.src.charCodeAt(this.pos);\n }\n else {\n return LexEOF;\n }\n }\n\n public peekCharAt(index: number): number {\n if (index < this.len) {\n return this.src.charCodeAt(index);\n }\n else {\n return LexEOF;\n }\n }\n\n public IsHexDigit(c: number) {\n return ((c >= LexCode_0) && (c <= LexCode_9)) || ((c >= LexCode_A) && (c <= LexCode_F)) ||\n ((c >= LexCode_a) && (c <= LexCode_f));\n }\n\n public IsOctalDigit(c: number) {\n return ((c >= LexCode_0) && (c <= LexCode_7)) ||\n ((c >= LexCode_a) && (c <= LexCode_f));\n }\n\n public scanHexDigits(): Token {\n var atLeastOneDigit = false;\n for (; ;) {\n if (this.IsHexDigit(this.ch)) {\n this.nextChar();\n atLeastOneDigit = true;\n }\n else {\n if (atLeastOneDigit) {\n return new NumberLiteralToken(parseInt(this.src.substring(this.startPos, this.pos)));\n }\n else {\n return null;\n }\n }\n }\n\n }\n\n public scanOctalDigits(): Token {\n var atLeastOneDigit = false;\n for (; ;) {\n if (this.IsOctalDigit(this.ch)) {\n this.nextChar();\n atLeastOneDigit = true;\n }\n else {\n if (atLeastOneDigit) {\n return new NumberLiteralToken(parseInt(this.src.substring(this.startPos, this.pos)));\n }\n else {\n return null;\n }\n }\n }\n\n }\n\n public scanDecimalNumber(state: number): Token {\n var atLeastOneDigit = false;\n var svPos = this.pos;\n var svCol = this.col;\n for (; ;) {\n if (LexIsDigit(this.ch)) {\n atLeastOneDigit = true;\n if (this.ch != LexCode_0 && state == NumberScanState.InEmptyFraction) {\n state = NumberScanState.InFraction;\n }\n this.nextChar();\n }\n else if (this.ch == LexCodeDOT) {\n if (state == NumberScanState.Start) {\n // DecimalDigit* .\n this.nextChar();\n state = NumberScanState.InEmptyFraction;\n }\n else {\n // dot not part of number\n if (atLeastOneDigit) {\n // DecimalDigit* . DecimalDigit+\n return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);\n }\n else {\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n }\n } else if ((this.ch == LexCode_e) || (this.ch == LexCode_E)) {\n if (state == NumberScanState.Start) {\n if (atLeastOneDigit) {\n // DecimalDigit+ (. DecimalDigit*) [eE] [+-]DecimalDigit+\n atLeastOneDigit = false;\n this.nextChar();\n state = NumberScanState.InExponent;\n }\n else {\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n }\n else if (state == NumberScanState.InFraction || state == NumberScanState.InEmptyFraction) {\n // DecimalDigit+ . DecimalDigit* [eE]\n this.nextChar();\n state = NumberScanState.InExponent;\n atLeastOneDigit = false;\n }\n else {\n // DecimalDigit+ . DecimalDigit* [eE] DecimalDigit+\n if (atLeastOneDigit) {\n return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)));\n }\n else {\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n }\n }\n else if ((this.ch == LexCodePLS) || (this.ch == LexCodeMIN)) {\n if (state == NumberScanState.InExponent) {\n if (!atLeastOneDigit) {\n this.nextChar();\n }\n else {\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n }\n else if (state == NumberScanState.InEmptyFraction || state == NumberScanState.InFraction) {\n // This case will not generate bad javascript if we miss the fractional part, but we just want to be consistent with the dot case\n return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);\n }\n else {\n if (!atLeastOneDigit) {\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n else {\n return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)));\n }\n }\n }\n else {\n if (!atLeastOneDigit) {\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n else {\n return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);\n }\n }\n }\n }\n\n // 0 [xX] hexDigits\n // 0 octalDigits\n // 0 [89] decimalDigits\n // decimalDigits? fraction? exponent?\n\n public scanNumber(): Token {\n if (this.peekChar() == LexCode_0) {\n switch (this.peekCharAt(this.pos + 1)) {\n case LexCode_x:\n case LexCode_X:\n // Hex\n this.advanceChar(2);\n return this.scanHexDigits();\n case LexCode_8:\n case LexCode_9:\n case LexCodeDOT:\n return this.scanDecimalNumber(NumberScanState.Start);\n default:\n // Octal\n return this.scanOctalDigits();\n }\n }\n else {\n return this.scanDecimalNumber(NumberScanState.Start);\n }\n }\n\n public scanFraction(): Token {\n return this.scanDecimalNumber(NumberScanState.InFraction);\n }\n\n public newLine() {\n this.col = 0;\n if (this.mode == LexMode.File) {\n this.line++;\n this.lineMap[this.line] = this.pos + 1;\n }\n }\n\n public finishMultilineComment(): bool {\n var ch2: number;\n this.lexState = LexState.InMultilineComment;\n while (this.pos < this.len) {\n if (this.ch == LexCodeMUL) {\n ch2 = this.peekCharAt(this.pos + 1);\n if (ch2 == LexCodeSLH) {\n this.advanceChar(2);\n if (this.mode == LexMode.File) {\n this.tokenStart();\n }\n this.lexState = LexState.Start;\n return true;\n }\n }\n else if (this.ch == LexCodeNWL) {\n this.newLine();\n if (this.mode == LexMode.Line) {\n this.nextChar();\n return false;\n }\n } \n else if (this.ch >= LexCodeASCIIChars) { \n this.seenUnicodeCharInComment = true;\n }\n this.nextChar();\n }\n return false;\n }\n\n public pushComment(comment: CommentToken) {\n this.commentStack.push(comment);\n }\n\n public getComments() {\n var stack = this.commentStack;\n this.commentStack = [];\n return stack;\n }\n\n public getCommentsForLine(line: number) {\n var comments: CommentToken[] = null;\n while ((this.commentStack.length > 0) && (this.commentStack[0].line == line)) {\n if (comments == null) {\n comments = [this.commentStack.shift()];\n }\n else {\n comments = comments.concat([this.commentStack.shift()]);\n }\n\n }\n return comments;\n }\n\n public resetComments() {\n this.commentStack = [];\n }\n\n public endsLine(c: number) {\n return (c == LexCodeNWL) || (c == LexCodeRET) || (c == LexCodeLS) || (c == LexCodePS);\n }\n\n public finishSinglelineComment() {\n while (this.pos < this.len) {\n if (this.endsLine(this.ch))\n break;\n if (this.ch >= LexCodeASCIIChars) { \n this.seenUnicodeCharInComment = true;\n }\n this.nextChar();\n }\n\n if (this.mode == LexMode.File) {\n this.tokenStart();\n }\n }\n\n public tokenText(): string {\n return this.src.substring(this.startPos, this.pos);\n }\n\n public findClosingSLH() {\n var index = this.pos;\n var ch2 = this.src.charCodeAt(index);\n var prevCh = 0;\n var liveEsc = false;\n while (!this.endsLine(ch2) && (index < this.len)) {\n if ((ch2 == LexCodeSLH) && (!liveEsc)) {\n return index;\n }\n prevCh = ch2;\n index++;\n if (liveEsc) {\n liveEsc = false;\n }\n else {\n liveEsc = (prevCh == LexCodeBSL);\n }\n\n ch2 = this.src.charCodeAt(index);\n }\n return -1;\n }\n\n public speculateRegex(): Token {\n if (noRegexTable[this.prevTok.tokenId] != undefined) {\n return null;\n }\n var svPos = this.pos;\n var svCol = this.col;\n // first char is '/' and has been skipped\n var index = this.findClosingSLH();\n if (index > 0) {\n // found closing /\n var pattern = this.src.substring(svPos, index);\n var flags = \"\";\n this.pos = index + 1;\n this.ch = this.peekChar();\n var flagsStart = this.pos;\n // TODO: check for duplicate flags\n while ((this.ch == LexCode_i) || (this.ch == LexCode_g) || (this.ch == LexCode_m)) {\n this.nextChar();\n }\n if ((this.pos - flagsStart) > 3) {\n return null;\n }\n else {\n flags = this.src.substring(flagsStart, this.pos);\n }\n var regex = undefined;\n try {\n regex = new RegExp(pattern, flags);\n }\n catch (regexException) {\n }\n if (regex) {\n // no line boundary in regex string\n this.col = svCol + (this.pos - this.startPos);\n return new RegularExpressionLiteralToken(regex);\n }\n }\n this.pos = svPos;\n this.col = svCol;\n return null;\n }\n\n public lastTokenHadNewline() {\n return this.prevLine != this.startLine;\n }\n\n public lastTokenLimChar() {\n return this.interveningWhitespace ? this.interveningWhitespacePos : this.startPos;\n }\n\n // use only when known not to skip line terminators\n public advanceChar(amt: number) {\n this.pos += amt;\n this.col += amt;\n this.ch = this.peekChar();\n }\n\n public nextChar() {\n this.pos++;\n this.col++;\n this.ch = this.peekChar();\n }\n\n public getLookAheadToken(): Token {\n // REVIEW: This method is only used for parsing varargs in lambda expressions. If this functionality is needed for more common cases, \n // it needs to be designed. \n // Look-ahead token needs to be integrated in the scanner design to allow for an efficient lookup.\n\n // Store the scanner state\n var prevLine = this.prevLine;\n var line = this.line;\n var col = this.col;\n var pos = this.pos;\n var startPos = this.startPos;\n var startCol = this.startCol;\n var startLine = this.startLine;\n var ch = this.ch;\n var prevTok = this.prevTok;\n var lexState = this.lexState;\n var interveningWhitespace = this.interveningWhitespace;\n var interveningWhitespacePos = this.interveningWhitespacePos;\n var leftCurlyCount = this.leftCurlyCount;\n var rightCurlyCount = this.rightCurlyCount;\n var seenUnicodeChar = this.seenUnicodeChar;\n var seenUnicodeCharInComment = this.seenUnicodeCharInComment;\n var commentStackLength = this.commentStack.length;\n\n var lookAheadToken = this.scan();\n\n // Restore state\n this.prevLine = prevLine;\n this.line = line;\n this.col = col;\n this.pos = pos;\n this.startPos = startPos;\n this.startCol = startCol;\n this.startLine = startLine;\n this.ch = ch;\n this.prevTok = prevTok;\n this.lexState = lexState;\n this.interveningWhitespace = interveningWhitespace;\n this.interveningWhitespacePos = interveningWhitespacePos;\n this.leftCurlyCount = leftCurlyCount;\n this.rightCurlyCount = rightCurlyCount;\n this.seenUnicodeChar = seenUnicodeChar;\n this.seenUnicodeCharInComment = seenUnicodeCharInComment;\n this.commentStack.length = commentStackLength;\n\n return lookAheadToken;\n }\n\n public scanInLine(): Token {\n if ((this.lexState == LexState.InMultilineComment) && (this.scanComments)) {\n this.ch = this.peekChar();\n var commentLine = this.line;\n this.finishMultilineComment();\n if (this.startPos < this.pos) {\n var commentText = this.src.substring(this.startPos, this.pos);\n this.tokenStart();\n return new CommentToken(TokenID.Comment, commentText,/*isBlock*/true, this.startPos, commentLine,/*endsLine*/true);\n }\n else {\n return staticTokens[TokenID.EndOfFile];\n }\n } \n else if (this.lexState == LexState.InMultilineSingleQuoteString && this.pos < this.len) { \n this.ch = LexCodeAPO;\n this.lexState = LexState.Start;\n return this.scanStringConstant();\n }\n else if (this.lexState == LexState.InMultilineDoubleQuoteString && this.pos < this.len) { \n this.ch = LexCodeQUO;\n this.lexState = LexState.Start;\n return this.scanStringConstant();\n }\n this.prevLine = this.line;\n var prevTok = this.innerScan();\n\n // Ingore white spaces\n if (prevTok.tokenId != TokenID.Whitespace) {\n this.prevTok = prevTok;\n }\n return prevTok;\n }\n\n public scan(): Token {\n this.prevLine = this.line;\n this.prevTok = this.innerScan();\n if (this.saveScan) {\n this.saveScan.addToken(this.prevTok, this);\n }\n return this.prevTok;\n }\n\n private isValidUnicodeIdentifierChar(): bool {\n var valid = LexIsUnicodeIdStart(this.ch) || LexIsUnicodeDigit(this.ch);\n this.seenUnicodeChar = this.seenUnicodeChar || valid;\n return valid;\n }\n\n private scanStringConstant(): Token {\n var endCode = this.ch;\n \n // Skip the first quote\n this.nextChar();\n \n // Accumulate with escape characters\n scanStringConstantLoop:\n for (;;) {\n switch (this.ch) {\n case LexEOF:\n // Unexpected end of file\n this.reportScannerError(\"Unterminated string constant\");\n break scanStringConstantLoop;\n\n case LexCodeLS:\n case LexCodePS:\n this.seenUnicodeChar = true;\n // Intentional fall through\n case LexCodeRET:\n case LexCodeNWL:\n this.reportScannerError(\"Unterminated string constant\");\n break scanStringConstantLoop;\n\n case LexCodeAPO:\n case LexCodeQUO:\n if (this.ch == endCode) {\n // Found string terminator. Skip past end code.\n this.nextChar();\n break scanStringConstantLoop;\n }\n break;\n\n case LexCodeBSL:\n // Consume the current slash\n this.nextChar();\n\n switch (this.ch) {\n case LexCodeAPO:\n case LexCodeQUO:\n case LexCodeBSL:\n // Valid escape sequences\n this.nextChar();\n continue scanStringConstantLoop;\n\n case LexCodeLS:\n case LexCodePS:\n this.seenUnicodeChar = true;\n // Intentional fall through\n case LexCodeRET:\n case LexCodeNWL:\n // Skip /r in a /r/n sequence\n if (this.ch == LexCodeRET && this.peekCharAt(this.pos + 1) == LexCodeNWL) {\n this.nextChar();\n }\n\n // Consume the new line char\n this.nextChar();\n\n // Record new line\n this.newLine();\n\n if (this.mode == LexMode.Line) {\n this.lexState = endCode == LexCodeAPO ? LexState.InMultilineSingleQuoteString : LexState.InMultilineDoubleQuoteString;\n break scanStringConstantLoop;\n }\n break;\n\n case LexCode_x:\n case LexCode_u:\n var expectedHexDigits = this.ch == LexCode_x ? 2 : 4;\n this.nextChar();\n for (var i = 0; i < expectedHexDigits; i++) {\n if (this.IsHexDigit(this.ch)) {\n this.nextChar();\n }\n else {\n this.reportScannerError(\"Invalid Unicode escape sequence\");\n break;\n }\n }\n continue scanStringConstantLoop;\n }\n break;\n }\n\n // Record seeing a Unicode char\n if (this.ch >= LexCodeASCIIChars) {\n this.seenUnicodeChar = true;\n }\n\n this.nextChar();\n }\n\n return new StringLiteralToken(this.src.substring(this.startPos, this.pos));\n }\n\n private scanIdentifier(): Token {\n var hasEscape = false;\n var isFirstChar = (this.ch == LexCodeBSL);\n var hasUnicode: any = false;\n\n for (; ;) {\n while (lexIdStartTable[this.ch] || LexIsDigit(this.ch) || \n (this.ch >= LexCodeASCIIChars && this.isValidUnicodeIdentifierChar())) {\n this.nextChar();\n }\n if (this.ch == LexCodeBSL) {\n this.nextChar();\n if (this.ch == LexCode_u) {\n // 4 hex digits\n this.nextChar();\n for (var h = 0; h < 4 ; h++) {\n if (this.IsHexDigit(this.ch)) {\n this.nextChar();\n }\n else {\n this.reportScannerError(\"Invalid Unicode escape sequence\");\n return staticTokens[TokenID.Error];\n }\n }\n var hexChar = parseInt(this.src.substring(this.pos - 4, this.pos), 16);\n\n // Verify is valid ID char \n if (lexIdStartTable[hexChar] || (!isFirstChar && LexIsDigit(hexChar)) ||\n (hexChar >= LexCodeASCIIChars && (LexIsUnicodeIdStart(hexChar) || (!isFirstChar && LexIsUnicodeDigit(hexChar))))) {\n }\n else { \n this.reportScannerError(\"Invalid identifier character\");\n return staticTokens[TokenID.Error];\n }\n\n hasEscape = true;\n isFirstChar = false;\n continue;\n }\n\n this.reportScannerError(\"Invalid Unicode escape sequence\");\n return staticTokens[TokenID.Error];\n }\n break;\n }\n\n var id: number;\n var text = this.src.substring(this.startPos, this.pos);\n if (!hasEscape && (id = LexKeywordTable.lookup(text)) != null) {\n return staticTokens[id];\n }\n else {\n return new IdentifierToken(text, hasEscape);\n }\n }\n\n public innerScan(): Token {\n var rtok;\n this.tokenStart();\n this.ch = this.peekChar();\n\n start: while (this.pos < this.len) {\n if (lexIdStartTable[this.ch] || this.ch == LexCodeBSL || (this.ch >= LexCodeASCIIChars && LexIsUnicodeIdStart(this.ch))) {\n // identifier or keyword\n return this.scanIdentifier();\n }\n else if (this.ch == LexCodeSpace) {\n if (!this.interveningWhitespace) {\n this.interveningWhitespacePos = this.pos;\n }\n do {\n this.nextChar();\n } while (this.ch == LexCodeSpace);\n if (this.mode == LexMode.Line) {\n var whitespaceText = this.src.substring(this.startPos, this.pos);\n return new WhitespaceToken(TokenID.Whitespace, whitespaceText);\n }\n else {\n this.tokenStart();\n this.interveningWhitespace = true;\n }\n }\n else if (this.ch == LexCodeSLH) {\n this.nextChar();\n var commentText;\n if (this.ch == LexCodeSLH) {\n if (!this.interveningWhitespace) {\n this.interveningWhitespacePos = this.pos - 1;\n }\n var commentStartPos = this.pos - 1;\n var commentStartLine = this.line;\n this.finishSinglelineComment();\n var commentText = this.src.substring(commentStartPos, this.pos);\n var commentToken = new CommentToken(TokenID.Comment, commentText,/*isBlock*/false, commentStartPos, commentStartLine,/*endsLine*/false);\n if (this.scanComments) {\n // respect scanner contract: when returning a token, startPos is the start position of the token\n this.startPos = commentStartPos;\n return commentToken;\n }\n else {\n this.pushComment(commentToken);\n }\n\n this.interveningWhitespace = true;\n }\n else if (this.ch == LexCodeMUL) {\n if (!this.interveningWhitespace) {\n this.interveningWhitespacePos = this.pos - 1;\n }\n var commentStartPos = this.pos - 1;\n var commentStartLine = this.line;\n this.nextChar(); // Skip the \"*\"\n this.finishMultilineComment();\n var commentText = this.src.substring(commentStartPos, this.pos);\n var endsLine = this.endsLine(this.peekChar());\n var commentToken = new CommentToken(TokenID.Comment, commentText,/*isBlock*/true, commentStartPos, commentStartLine, endsLine);\n if (this.scanComments) {\n // respect scanner contract: when returning a token, startPos is the start position of the token\n this.startPos = commentStartPos;\n return commentToken;\n }\n else {\n this.pushComment(commentToken);\n }\n this.interveningWhitespace = true;\n }\n else {\n var regexTok = this.speculateRegex();\n if (regexTok) {\n return regexTok;\n }\n else {\n if (this.peekCharAt(this.pos) == LexCodeEQ) {\n this.nextChar();\n return staticTokens[TokenID.SlashEquals];\n }\n else {\n return staticTokens[TokenID.Slash];\n }\n }\n }\n }\n else if (this.ch == LexCodeSMC) {\n this.nextChar();\n return staticTokens[TokenID.Semicolon];\n }\n else if ((this.ch == LexCodeAPO) || (this.ch == LexCodeQUO)) {\n return this.scanStringConstant();\n }\n else if (autoToken[this.ch]) {\n var atok = autoToken[this.ch];\n if (atok.tokenId == TokenID.OpenBrace) {\n this.leftCurlyCount++;\n }\n else if (atok.tokenId == TokenID.CloseBrace) {\n this.rightCurlyCount++;\n }\n this.nextChar();\n return atok;\n }\n else if ((this.ch >= LexCode_0) && (this.ch <= LexCode_9)) {\n rtok = this.scanNumber();\n if (rtok) {\n return rtok;\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Error];\n }\n }\n else switch (this.ch) {\n // TAB\n case LexCodeTAB:\n case LexCodeVTAB:\n if (!this.interveningWhitespace) {\n this.interveningWhitespacePos = this.pos;\n }\n if (this.mode == LexMode.Line) {\n do {\n this.nextChar();\n } while ((this.ch == LexCodeSpace) || (this.ch == 9));\n var wsText = this.src.substring(this.startPos, this.pos);\n return new WhitespaceToken(TokenID.Whitespace, wsText);\n }\n else {\n this.interveningWhitespace = true;\n }\n // Newlines and BOM\n case 0xFF: // UTF16 SEQUENCE\n case 0xFE:\n case 0xEF: // UTF8 SEQUENCE\n case 0xBB:\n case 0xBF:\n case LexCodeLS:\n case LexCodePS:\n case LexCodeNWL:\n case LexCodeRET:\n if (this.ch == LexCodeNWL) {\n this.newLine();\n if (this.mode == LexMode.Line) {\n return staticTokens[TokenID.EndOfFile];\n }\n }\n if (!this.interveningWhitespace) {\n this.interveningWhitespacePos = this.pos;\n }\n this.nextChar();\n this.tokenStart();\n this.interveningWhitespace = true;\n break;\n case LexCodeDOT: {\n if (this.peekCharAt(this.pos + 1) == LexCodeDOT) {\n if (this.peekCharAt(this.pos + 2) == LexCodeDOT) {\n this.advanceChar(3);\n return staticTokens[TokenID.DotDotDot];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Dot];\n }\n }\n else {\n this.nextChar();\n rtok = this.scanFraction();\n if (rtok) {\n return rtok;\n }\n else {\n return staticTokens[TokenID.Dot];\n }\n }\n // break;\n }\n case LexCodeEQ:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n this.advanceChar(3);\n return staticTokens[TokenID.EqualsEqualsEquals];\n }\n else {\n this.advanceChar(2);\n return staticTokens[TokenID.EqualsEquals];\n }\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodeGT) {\n this.advanceChar(2);\n return staticTokens[TokenID.EqualsGreaterThan];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Equals];\n }\n // break;\n case LexCodeBNG:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n this.advanceChar(3);\n return staticTokens[TokenID.ExclamationEqualsEquals];\n }\n else {\n this.advanceChar(2);\n return staticTokens[TokenID.ExclamationEquals];\n }\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Exclamation];\n }\n // break;\n case LexCodePLS:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.PlusEquals];\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodePLS) {\n this.advanceChar(2);\n return staticTokens[TokenID.PlusPlus];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Plus];\n }\n // break;\n case LexCodeMIN:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.MinusEquals];\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodeMIN) {\n this.advanceChar(2);\n return staticTokens[TokenID.MinusMinus];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Minus];\n }\n // break;\n case LexCodeMUL:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.AsteriskEquals];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Asterisk];\n }\n // break;\n case LexCodePCT:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.PercentEquals];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Percent];\n }\n // break;\n case LexCodeLT:\n if (this.peekCharAt(this.pos + 1) == LexCodeLT) {\n if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n this.advanceChar(3);\n return staticTokens[TokenID.LessThanLessThanEquals];\n }\n else {\n this.advanceChar(2);\n return staticTokens[TokenID.LessThanLessThan];\n }\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.LessThanEquals];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.LessThan];\n }\n // break;\n case LexCodeGT:\n if (this.peekCharAt(this.pos + 1) == LexCodeGT) {\n if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n this.advanceChar(3);\n return staticTokens[TokenID.GreaterThanGreaterThanEquals];\n }\n else if (this.peekCharAt(this.pos + 2) == LexCodeGT) {\n if (this.peekCharAt(this.pos + 3) == LexCodeEQ) {\n this.advanceChar(4);\n return staticTokens[TokenID.GreaterThanGreaterThanGreaterThanEquals];\n }\n else {\n this.advanceChar(3);\n return staticTokens[TokenID.GreaterThanGreaterThanGreaterThan];\n }\n }\n else {\n this.advanceChar(2);\n return staticTokens[TokenID.GreaterThanGreaterThan];\n }\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.GreaterThanEquals];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.GreaterThan];\n }\n // break;\n case LexCodeXOR:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.CaretEquals];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Caret];\n }\n // break;\n case LexCodeBAR:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.BarEquals];\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodeBAR) {\n this.advanceChar(2);\n return staticTokens[TokenID.BarBar];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.Bar];\n }\n // break;\n case LexCodeAMP:\n if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n this.advanceChar(2);\n return staticTokens[TokenID.AmpersandEquals];\n }\n else if (this.peekCharAt(this.pos + 1) == LexCodeAMP) {\n this.advanceChar(2);\n return staticTokens[TokenID.AmpersandAmpersand];\n }\n else {\n this.nextChar();\n return staticTokens[TokenID.And];\n }\n // break;\n default:\n // Report error\n this.reportScannerError(\"Invalid character\");\n this.nextChar();\n\n continue start;\n }\n }\n return staticTokens[TokenID.EndOfFile];\n }\n\n private reportScannerError(message: string) { \n if (this.reportError) { \n this.reportError(message);\n }\n }\n }\n\n // Reseverved words only apply to Identifiers, not IdentifierNames\n export function convertTokToIDName(tok: Token): bool {\n return convertTokToIDBase(tok, true, false);\n }\n\n export function convertTokToID(tok: Token, strictMode: bool): bool {\n return convertTokToIDBase(tok, false, strictMode);\n }\n\n function convertTokToIDBase(tok: Token, identifierName: bool, strictMode: bool): bool {\n if (tok.tokenId <= TokenID.LimKeyword) {\n var tokInfo = lookupToken(tok.tokenId);\n if (tokInfo != undefined) {\n var resFlags = Reservation.Javascript | Reservation.JavascriptFuture;\n if (strictMode) {\n resFlags |= Reservation.JavascriptFutureStrict;\n }\n if (identifierName || !hasFlag(tokInfo.reservation, resFlags)) {\n return true;\n }\n }\n else {\n return false;\n }\n }\n else {\n return false;\n }\n }\n\n // Return the (1-based) line number from a character offset using the provided linemap.\n export function getLineNumberFromPosition(lineMap: number[], position: number): number {\n if (position === -1)\n return 0;\n\n // Binary search\n var min = 0;\n var max = lineMap.length - 1;\n while (min < max) {\n var med = (min + max) >> 1;\n if (position < lineMap[med]) {\n max = med - 1;\n }\n else if (position < lineMap[med + 1]) {\n min = max = med; // found it\n }\n else {\n min = med + 1;\n }\n }\n\n return min;\n }\n\n /// Return the [line, column] data for a given offset and a lineMap.\n /// Note that the returned line is 1-based, while the column is 0-based.\n export function getSourceLineColFromMap(lineCol: ILineCol, minChar: number, lineMap: number[]): void {\n var line = getLineNumberFromPosition(lineMap, minChar);\n\n if (line > 0) {\n lineCol.line = line;\n lineCol.col = (minChar - lineMap[line]);\n }\n }\n\n // Return the [line, column] (both 1 based) corresponding to a given position in a given script.\n export function getLineColumnFromPosition(script: TypeScript.Script, position: number): ILineCol {\n var result = { line: -1, col: -1 };\n getSourceLineColFromMap(result, position, script.locationInfo.lineMap);\n if (result.col >= 0) {\n result.col++; // Make it 1-based\n }\n return result;\n }\n\n //\n // Return the position (offset) corresponding to a given [line, column] (both 1-based) in a given script.\n //\n export function getPositionFromLineColumn(script: TypeScript.Script, line: number, column: number): number {\n return script.locationInfo.lineMap[line] + (column - 1);\n }\n \n // Return true if the token is a primitive type\n export function isPrimitiveTypeToken(token: Token) {\n switch (token.tokenId) {\n case TokenID.Any:\n case TokenID.Bool:\n case TokenID.Number:\n case TokenID.String:\n return true;\n }\n return false;\n }\n\n // Return true if the token is a primitive type\n export function isModifier(token: Token) {\n switch (token.tokenId) {\n case TokenID.Public:\n case TokenID.Private:\n case TokenID.Static:\n return true;\n }\n return 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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export class AssignScopeContext {\n constructor (public scopeChain: ScopeChain,\n public typeFlow: TypeFlow,\n public modDeclChain: ModuleDeclaration[]) {\n }\n }\n\n export function pushAssignScope(scope: SymbolScope,\n context: AssignScopeContext,\n type: Type,\n classType: Type,\n fnc: FuncDecl) {\n\n var chain = new ScopeChain(null, context.scopeChain, scope);\n chain.thisType = type;\n chain.classType = classType;\n chain.fnc = fnc;\n context.scopeChain = chain;\n }\n\n export function popAssignScope(context: AssignScopeContext) {\n context.scopeChain = context.scopeChain.previous;\n }\n\n export function instanceCompare(a: Symbol, b: Symbol) {\n if (((a == null) || (!a.isInstanceProperty()))) {\n return b;\n }\n else {\n return a;\n }\n }\n\n export function instanceFilterStop(s: Symbol) {\n return s.isInstanceProperty();\n }\n\n export class ScopeSearchFilter {\n\n constructor (public select: (a: Symbol, b: Symbol) =>Symbol,\n public stop: (s: Symbol) =>bool) { }\n\n public result: Symbol = null;\n\n public reset() {\n this.result = null;\n }\n\n public update(b: Symbol): bool {\n this.result = this.select(this.result, b);\n if (this.result) {\n return this.stop(this.result);\n }\n else {\n return false;\n }\n }\n }\n\n export var instanceFilter = new ScopeSearchFilter(instanceCompare, instanceFilterStop);\n\n export function preAssignModuleScopes(ast: AST, context: AssignScopeContext) {\n var moduleDecl = <ModuleDeclaration>ast;\n var memberScope: SymbolTableScope = null;\n var aggScope: SymbolAggregateScope = null;\n\n if (moduleDecl.name && moduleDecl.mod) {\n moduleDecl.name.sym = moduleDecl.mod.symbol;\n }\n\n var mod = moduleDecl.mod;\n\n // We're likely here because of error recovery\n if (!mod) {\n return;\n }\n\n memberScope = new SymbolTableScope(mod.members, mod.ambientMembers, mod.enclosedTypes, mod.ambientEnclosedTypes, mod.symbol);\n mod.memberScope = memberScope;\n context.modDeclChain.push(moduleDecl);\n context.typeFlow.checker.currentModDecl = moduleDecl;\n aggScope = new SymbolAggregateScope(mod.symbol);\n aggScope.addParentScope(memberScope);\n aggScope.addParentScope(context.scopeChain.scope);\n pushAssignScope(aggScope, context, null, null, null);\n mod.containedScope = aggScope;\n if (mod.symbol) {\n context.typeFlow.addLocalsFromScope(mod.containedScope, mod.symbol, moduleDecl.vars, mod.members.privateMembers, true);\n }\n }\n\n export function preAssignClassScopes(ast: AST, context: AssignScopeContext) {\n var classDecl = <InterfaceDeclaration>ast;\n var memberScope: SymbolTableScope = null;\n var aggScope: SymbolAggregateScope = null;\n\n if (classDecl.name && classDecl.type) {\n classDecl.name.sym = classDecl.type.symbol;\n }\n\n var classType = ast.type;\n\n if (classType) {\n var classSym = classType.symbol;\n memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(classType);\n\n aggScope = new SymbolAggregateScope(classType.symbol);\n aggScope.addParentScope(memberScope);\n aggScope.addParentScope(context.scopeChain.scope);\n\n classType.containedScope = aggScope;\n classType.memberScope = memberScope;\n\n var instanceType = classType.instanceType;\n memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(instanceType);\n instanceType.memberScope = memberScope;\n\n aggScope = new SymbolAggregateScope(instanceType.symbol);\n aggScope.addParentScope(context.scopeChain.scope);\n\n pushAssignScope(aggScope, context, instanceType, classType, null);\n instanceType.containedScope = aggScope;\n }\n else {\n ast.type = context.typeFlow.anyType;\n }\n }\n\n export function preAssignInterfaceScopes(ast: AST, context: AssignScopeContext) {\n var interfaceDecl = <InterfaceDeclaration>ast;\n var memberScope: SymbolTableScope = null;\n var aggScope: SymbolAggregateScope = null;\n\n if (interfaceDecl.name && interfaceDecl.type) {\n interfaceDecl.name.sym = interfaceDecl.type.symbol;\n }\n\n var interfaceType = ast.type;\n memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(interfaceType);\n interfaceType.memberScope = memberScope;\n aggScope = new SymbolAggregateScope(interfaceType.symbol);\n aggScope.addParentScope(memberScope);\n aggScope.addParentScope(context.scopeChain.scope);\n pushAssignScope(aggScope, context, null, null, null);\n interfaceType.containedScope = aggScope;\n }\n\n export function preAssignWithScopes(ast: AST, context: AssignScopeContext) {\n var withStmt = <WithStatement>ast;\n var withType = withStmt.type;\n\n var members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n var ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n var withType = new Type();\n var withSymbol = new WithSymbol(withStmt.minChar, context.typeFlow.checker.locationInfo.unitIndex, withType);\n withType.members = members;\n withType.ambientMembers = ambientMembers;\n withType.symbol = withSymbol;\n withType.setHasImplementation();\n withStmt.type = withType;\n\n var withScope = new TypeScript.SymbolScopeBuilder(withType.members, withType.ambientMembers, null, null, context.scopeChain.scope, withType.symbol);\n\n pushAssignScope(withScope, context, null, null, null);\n withType.containedScope = withScope;\n }\n\n export function preAssignFuncDeclScopes(ast: AST, context: AssignScopeContext) {\n var funcDecl = <FuncDecl>ast;\n\n var container: Symbol = null;\n var localContainer: Symbol = null;\n if (funcDecl.type) {\n localContainer = ast.type.symbol;\n }\n\n var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n var isInnerStatic = isStatic && context.scopeChain.fnc != null;\n // for inner static functions, use the parent's member scope, so local vars cannot be captured\n var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope;\n\n // if this is not a method, but enclosed by class, use constructor as\n // the enclosing scope\n // REVIEW: Some twisted logic here - this needs to be cleaned up once old classes are removed\n // - if it's a new class, always use the contained scope, since we initialize the constructor scope below\n if (context.scopeChain.thisType &&\n (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod))) {\n var instType = context.scopeChain.thisType;\n\n if (!(instType.typeFlags & TypeFlags.IsClass) && !hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n if (!funcDecl.isMethod() || isStatic) {\n parentScope = instType.constructorScope;\n }\n else {\n // use constructor scope if a method as well\n parentScope = instType.containedScope;\n }\n }\n else {\n if (context.scopeChain.previous.scope.container &&\n context.scopeChain.previous.scope.container.declAST &&\n context.scopeChain.previous.scope.container.declAST.nodeType == NodeType.FuncDecl &&\n (<FuncDecl>context.scopeChain.previous.scope.container.declAST).isConstructor) {\n\n // if the parent is the class constructor, use the constructor scope\n parentScope = instType.constructorScope;\n }\n else if (isStatic && context.scopeChain.classType) {\n parentScope = context.scopeChain.classType.containedScope;\n }\n else {\n // else, use the contained scope\n parentScope = instType.containedScope;\n }\n }\n container = instType.symbol;\n }\n else if (funcDecl.isConstructor && context.scopeChain.thisType) {\n // sets the container to the class type's symbol (which is shared by the instance type)\n container = context.scopeChain.thisType.symbol;\n }\n\n if (funcDecl.type == null || hasFlag(funcDecl.type.symbol.flags, SymbolFlags.TypeSetDuringScopeAssignment)) {\n if (context.scopeChain.fnc && context.scopeChain.fnc.type) {\n container = context.scopeChain.fnc.type.symbol;\n }\n\n var funcScope = null;\n var outerFnc: FuncDecl = context.scopeChain.fnc;\n var nameText = funcDecl.name ? funcDecl.name.actualText : null;\n var fgSym: TypeSymbol = null;\n\n if (isStatic) {\n // In the case of function-nested statics, no member list will have bee initialized for the function, so we need\n // to copy it over. We don't set this by default because having a non-null member list will throw off assignment\n // compatibility tests\n if (outerFnc.type.members == null && container.getType().memberScope) {\n outerFnc.type.members = (<SymbolScopeBuilder>(<TypeSymbol>container).type.memberScope).valueMembers;\n }\n funcScope = context.scopeChain.fnc.type.memberScope;\n outerFnc.innerStaticFuncs[outerFnc.innerStaticFuncs.length] = funcDecl;\n }\n else {\n funcScope = context.scopeChain.scope;\n }\n\n // REVIEW: We don't search for another sym for accessors to prevent us from\n // accidentally coalescing function signatures with the same name (E.g., a function\n // 'f' the outer scope and a setter 'f' in an object literal within that scope)\n if (nameText && nameText != \"__missing\" && !funcDecl.isAccessor()) {\n if (isStatic) {\n fgSym = funcScope.findLocal(nameText, false, false);\n }\n else {\n // REVIEW: This logic should be symmetric with preCollectClassTypes\n fgSym = funcScope.findLocal(nameText, false, false);\n }\n }\n\n context.typeFlow.checker.createFunctionSignature(funcDecl, container,\n funcScope, fgSym, fgSym == null);\n\n // it's a getter or setter for a class property \n if (!funcDecl.accessorSymbol && \n (funcDecl.fncFlags & FncFlags.ClassMethod) &&\n container && \n ((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) || \n (fgSym && fgSym.isAccessor())) \n {\n funcDecl.accessorSymbol = context.typeFlow.checker.createAccessorSymbol(funcDecl, fgSym, container.getType(), (funcDecl.isMethod() && isStatic), true, funcScope, container);\n }\n\n funcDecl.type.symbol.flags |= SymbolFlags.TypeSetDuringScopeAssignment;\n }\n\n // Set the symbol for functions and their overloads\n if (funcDecl.name && funcDecl.type) {\n funcDecl.name.sym = funcDecl.type.symbol;\n }\n\n // Keep track of the original scope type, because target typing might override\n // the \"type\" member. We need the original \"Scope type\" for completion list, etc.\n funcDecl.scopeType = funcDecl.type;\n\n // Overloads have no scope, so bail here\n if (funcDecl.isOverload) {\n return;\n }\n\n var funcTable = new StringHashTable();\n var funcMembers = new ScopedMembers(new DualStringHashTable(funcTable, new StringHashTable()));\n var ambientFuncTable = new StringHashTable();\n var ambientFuncMembers = new ScopedMembers(new DualStringHashTable(ambientFuncTable, new StringHashTable()));\n var funcStaticTable = new StringHashTable();\n var funcStaticMembers = new ScopedMembers(new DualStringHashTable(funcStaticTable, new StringHashTable()));\n var ambientFuncStaticTable = new StringHashTable();\n var ambientFuncStaticMembers = new ScopedMembers(new DualStringHashTable(ambientFuncStaticTable, new StringHashTable()));\n\n // REVIEW: Is it a problem that this is being set twice for properties and constructors?\n funcDecl.unitIndex = context.typeFlow.checker.locationInfo.unitIndex;\n\n var locals = new SymbolScopeBuilder(funcMembers, ambientFuncMembers, null, null, parentScope, localContainer);\n var statics = new SymbolScopeBuilder(funcStaticMembers, ambientFuncStaticMembers, null, null, parentScope, null);\n\n if (funcDecl.isConstructor && context.scopeChain.thisType) {\n context.scopeChain.thisType.constructorScope = locals;\n }\n\n // basically, there are two problems\n // - Above, for new classes, we were overwriting the constructor scope with the containing scope. This caused constructor params to be\n // in scope everywhere\n // - Below, we're setting the contained scope table to the same table we were overwriting the constructor scope with, which we need to\n // fish lambda params, etc, out (see funcTable below)\n //\n // A good first approach to solving this would be to change addLocalsFromScope to take a scope instead of a table, and add to the\n // constructor scope as appropriate\n\n funcDecl.symbols = funcTable;\n\n if (!funcDecl.isSpecialFn()) {\n var group = funcDecl.type;\n var signature = funcDecl.signature;\n\n if (!funcDecl.isConstructor) {\n group.containedScope = locals;\n locals.container = group.symbol;\n\n group.memberScope = statics;\n statics.container = group.symbol;\n }\n funcDecl.enclosingFnc = context.scopeChain.fnc;\n group.enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType;\n // for mapping when type checking\n var fgSym = <TypeSymbol>ast.type.symbol;\n if (((funcDecl.fncFlags & FncFlags.Signature) == FncFlags.None) && funcDecl.vars) {\n context.typeFlow.addLocalsFromScope(locals, fgSym, funcDecl.vars,\n funcTable, false);\n context.typeFlow.addLocalsFromScope(statics, fgSym, funcDecl.statics,\n funcStaticTable, false);\n }\n if (signature.parameters) {\n var len = signature.parameters.length;\n for (var i = 0; i < len; i++) {\n var paramSym: ParameterSymbol = signature.parameters[i];\n context.typeFlow.checker.resolveTypeLink(locals,\n paramSym.parameter.typeLink, true);\n }\n }\n context.typeFlow.checker.resolveTypeLink(locals, signature.returnType,\n funcDecl.isSignature());\n }\n\n if (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n var thisType = (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) ? context.scopeChain.thisType : null;\n pushAssignScope(locals, context, thisType, null, funcDecl);\n }\n\n if (funcDecl.name && hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression)) {\n // If the function is an expression, the name will not be visible in the enclosing scope.\n // Add the function symbol under its name to the local scope to allow for recursive calls.\n if (funcDecl.name.sym) {\n funcTable.add(funcDecl.name.actualText, funcDecl.name.sym);\n }\n }\n }\n\n export function preAssignCatchScopes(ast: AST, context: AssignScopeContext) {\n var catchBlock = <Catch>ast;\n if (catchBlock.param) {\n var catchTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable())); // REVIEW: Should we be allocating a public table instead of a private one?\n var catchLocals = new SymbolScopeBuilder(catchTable, null, null, null, context.scopeChain.scope,\n context.scopeChain.scope.container);\n catchBlock.containedScope = catchLocals;\n pushAssignScope(catchLocals, context, context.scopeChain.thisType, context.scopeChain.classType, context.scopeChain.fnc);\n }\n }\n\n export function preAssignScopes(ast: AST, parent: AST, walker: IAstWalker) {\n var context:AssignScopeContext = walker.state;\n var go = true;\n\n if (ast) {\n if (ast.nodeType == NodeType.List) {\n var list = <ASTList>ast;\n list.enclosingScope = context.scopeChain.scope;\n }\n else if (ast.nodeType == NodeType.ModuleDeclaration) {\n preAssignModuleScopes(ast, context);\n }\n else if (ast.nodeType == NodeType.ClassDeclaration) {\n preAssignClassScopes(ast, context);\n }\n else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n preAssignInterfaceScopes(ast, context);\n }\n else if (ast.nodeType == NodeType.With) {\n preAssignWithScopes(ast, context);\n }\n else if (ast.nodeType == NodeType.FuncDecl) {\n preAssignFuncDeclScopes(ast, context);\n }\n else if (ast.nodeType == NodeType.Catch) {\n preAssignCatchScopes(ast, context);\n }\n else if (ast.nodeType == NodeType.TypeRef) {\n go = false;\n }\n }\n walker.options.goChildren = go;\n return ast;\n }\n\n export function postAssignScopes(ast: AST, parent: AST, walker: IAstWalker) {\n var context:AssignScopeContext = walker.state;\n var go = true;\n if (ast) {\n if (ast.nodeType == NodeType.ModuleDeclaration) {\n var prevModDecl = <ModuleDeclaration>ast;\n\n popAssignScope(context);\n\n context.modDeclChain.pop();\n if (context.modDeclChain.length >= 1) {\n context.typeFlow.checker.currentModDecl = context.modDeclChain[context.modDeclChain.length - 1];\n }\n }\n else if (ast.nodeType == NodeType.ClassDeclaration) {\n popAssignScope(context);\n }\n else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n popAssignScope(context);\n }\n else if (ast.nodeType == NodeType.With) {\n popAssignScope(context);\n }\n else if (ast.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>ast;\n if ((!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) && !funcDecl.isOverload) {\n popAssignScope(context);\n }\n }\n else if (ast.nodeType == NodeType.Catch) {\n var catchBlock = <Catch>ast;\n if (catchBlock.param) {\n popAssignScope(context);\n }\n }\n else {\n go = false;\n }\n }\n walker.options.goChildren = go;\n return ast;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class TypeCollectionContext {\n public script: Script = null;\n\n constructor (public scopeChain: ScopeChain, public checker: TypeChecker) {\n }\n }\n\n export class MemberScopeContext {\n public type: Type = null;\n public ast: AST = null;\n public scope: SymbolScope;\n public options = new AstWalkOptions();\n\n constructor (public flow: TypeFlow, public pos: number, public matchFlag: ASTFlags) {\n }\n }\n\n export class EnclosingScopeContext {\n\n public scopeGetter: () => SymbolScope = null;\n public objectLiteralScopeGetter: () => SymbolScope = null;\n public scopeStartAST: AST = null;\n public skipNextFuncDeclForClass = false;\n public deepestModuleDecl: ModuleDeclaration = null;\n public enclosingClassDecl: TypeDeclaration = null;\n public enclosingObjectLit: UnaryExpression = null;\n public publicsOnly = true;\n public useFullAst = false;\n private scriptFragment: Script;\n\n constructor (public logger: ILogger,\n public script: Script,\n public text: ISourceText,\n public pos: number,\n public isMemberCompletion: bool) {\n }\n\n public getScope(): SymbolScope {\n return this.scopeGetter();\n }\n\n public getObjectLiteralScope(): SymbolScope {\n return this.objectLiteralScopeGetter();\n }\n\n public getScopeAST() {\n return this.scopeStartAST;\n }\n\n public getScopePosition() {\n return this.scopeStartAST.minChar;\n }\n\n public getScriptFragmentStartAST(): AST {\n return this.scopeStartAST;\n }\n\n public getScriptFragmentPosition(): number {\n return this.getScriptFragmentStartAST().minChar;\n }\n\n public getScriptFragment(): Script {\n if (this.scriptFragment == null) {\n var ast = this.getScriptFragmentStartAST();\n var minChar = ast.minChar;\n var limChar = (this.isMemberCompletion ? this.pos : this.pos + 1);\n this.scriptFragment = TypeScript.quickParse(this.logger, ast, this.text, minChar, limChar, null/*errorCapture*/).Script;\n }\n return this.scriptFragment;\n }\n }\n\n export function preFindMemberScope(ast: AST, parent: AST, walker: IAstWalker) {\n var memScope: MemberScopeContext = walker.state;\n if (hasFlag(ast.flags, memScope.matchFlag) && ((memScope.pos < 0) || (memScope.pos == ast.limChar))) {\n memScope.ast = ast;\n if ((ast.type == null) && (memScope.pos >= 0)) {\n memScope.flow.inScopeTypeCheck(ast, memScope.scope);\n }\n memScope.type = ast.type;\n memScope.options.stopWalk();\n }\n return ast;\n }\n\n export function pushTypeCollectionScope(container: Symbol,\n valueMembers: ScopedMembers,\n ambientValueMembers: ScopedMembers,\n enclosedTypes: ScopedMembers,\n ambientEnclosedTypes: ScopedMembers,\n context: TypeCollectionContext,\n thisType: Type,\n classType: Type,\n moduleDecl: ModuleDeclaration) {\n var builder = new SymbolScopeBuilder(valueMembers, ambientValueMembers, enclosedTypes, ambientEnclosedTypes, null, container);\n var chain: ScopeChain = new ScopeChain(container, context.scopeChain, builder);\n chain.thisType = thisType;\n chain.classType = classType;\n chain.moduleDecl = moduleDecl;\n context.scopeChain = chain;\n }\n\n export function popTypeCollectionScope(context: TypeCollectionContext) {\n context.scopeChain = context.scopeChain.previous;\n }\n\n export function preFindEnclosingScope(ast: AST, parent: AST, walker: IAstWalker) {\n var context: EnclosingScopeContext = walker.state;\n var minChar = ast.minChar;\n var limChar = ast.limChar;\n\n // Account for the fact completion list may be called at the end of a file which\n // is has not been fully re-parsed yet.\n if (ast.nodeType == NodeType.Script && context.pos > limChar)\n limChar = context.pos;\n\n if ((minChar <= context.pos) &&\n (limChar >= context.pos)) {\n switch (ast.nodeType) {\n case NodeType.Script:\n var script = <Script>ast;\n context.scopeGetter = function () {\n return script.bod === null ? null : script.bod.enclosingScope;\n };\n context.scopeStartAST = script;\n break;\n\n case NodeType.ClassDeclaration:\n context.scopeGetter = function () {\n return (ast.type === null || ast.type.instanceType.containedScope === null) ? null : ast.type.instanceType.containedScope;\n };\n context.scopeStartAST = ast;\n context.enclosingClassDecl = <TypeDeclaration>ast;\n break;\n\n case NodeType.ObjectLit:\n var objectLit = <UnaryExpression>ast;\n // Only consider target-typed object literals\n if (objectLit.targetType) {\n context.scopeGetter = function () {\n return objectLit.targetType.containedScope;\n };\n context.objectLiteralScopeGetter = function () {\n return objectLit.targetType.memberScope;\n }\n context.enclosingObjectLit = objectLit;\n }\n break;\n\n case NodeType.ModuleDeclaration:\n context.deepestModuleDecl = <ModuleDeclaration>ast;\n context.scopeGetter = function () {\n return ast.type === null ? null : ast.type.containedScope;\n };\n context.scopeStartAST = ast;\n break;\n\n case NodeType.InterfaceDeclaration:\n context.scopeGetter = function () {\n return (ast.type === null) ? null : ast.type.containedScope;\n };\n context.scopeStartAST = ast;\n break;\n\n case NodeType.FuncDecl: {\n var funcDecl = <FuncDecl>ast;\n if (context.skipNextFuncDeclForClass) {\n context.skipNextFuncDeclForClass = false;\n }\n else {\n context.scopeGetter = function () {\n // The scope of a class constructor is hidden somewhere we don't expect :-S\n if (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n if (ast.type && ast.type.enclosingType) {\n return ast.type.enclosingType.constructorScope;\n }\n }\n\n if (funcDecl.scopeType) {\n return funcDecl.scopeType.containedScope;\n }\n\n if (funcDecl.type) {\n return funcDecl.type.containedScope;\n }\n return null;\n };\n context.scopeStartAST = ast;\n }\n }\n break;\n }\n walker.options.goChildren = true;\n }\n else {\n walker.options.goChildren = false;\n }\n return ast;\n }\n\n //\n // Find the enclosing scope context from a position inside a script AST.\n // The \"scopeStartAST\" of the returned scope is always valid.\n // Return \"null\" if the enclosing scope can't be found.\n //\n export function findEnclosingScopeAt(logger: ILogger, script: Script, text: ISourceText, pos: number, isMemberCompletion: bool): EnclosingScopeContext {\n var context = new EnclosingScopeContext(logger, script, text, pos, isMemberCompletion);\n\n TypeScript.getAstWalkerFactory().walk(script, preFindEnclosingScope, null, null, context);\n\n if (context.scopeStartAST === null)\n return null;\n return context;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class Signature {\n public hasVariableArgList = false;\n public returnType: TypeLink;\n public parameters: ParameterSymbol[] = null;\n public declAST: FuncDecl = null;\n public typeCheckStatus = TypeCheckStatus.NotStarted;\n public nonOptionalParameterCount = 0;\n\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Signature {\n var result = new Signature();\n if (this.hasVariableArgList) {\n result.hasVariableArgList = true;\n }\n result.returnType = new TypeLink();\n if (this.returnType.type) {\n result.returnType.type =\n this.returnType.type.specializeType(pattern, replacement, checker, false);\n }\n else {\n result.returnType.type = checker.anyType;\n }\n\n if (this.parameters) {\n result.parameters = [];\n for (var i = 0, len = this.parameters.length; i < len; i++) {\n var oldSym:ParameterSymbol = this.parameters[i];\n var paramDef = new ValueLocation();\n var paramSym = new ParameterSymbol(oldSym.name, oldSym.location,\n checker.locationInfo.unitIndex,\n paramDef);\n\n paramSym.declAST = this.declAST;\n paramDef.symbol = paramSym;\n paramDef.typeLink = new TypeLink();\n result.parameters[i] = paramSym;\n var oldType = oldSym.getType();\n if (oldType) {\n paramDef.typeLink.type = oldType.specializeType(pattern, replacement, checker, false);\n paramSym.declAST.type = paramDef.typeLink.type;\n }\n else {\n paramDef.typeLink.type = checker.anyType;\n }\n }\n }\n result.nonOptionalParameterCount = this.nonOptionalParameterCount;\n result.declAST = this.declAST;\n\n return result;\n }\n\n public toString() {\n return this.toStringHelper(false, false, null);\n }\n\n public toStringHelper(shortform: bool, brackets: bool, scope: SymbolScope) {\n return this.toStringHelperEx(shortform, brackets, scope).toString();\n }\n\n public toStringHelperEx(shortform: bool, brackets: bool, scope: SymbolScope, prefix? : string = \"\") : MemberName {\n var builder = new MemberNameArray();\n if (brackets) {\n builder.prefix = prefix + \"[\";\n }\n else {\n builder.prefix = prefix + \"(\";\n }\n\n var paramLen = this.parameters.length;\n var len = this.hasVariableArgList ? paramLen - 1 : paramLen;\n for (var i = 0; i < len; i++) {\n builder.add(MemberName.create(this.parameters[i].name + (this.parameters[i].isOptional() ? \"?\" : \"\") + \": \"));\n builder.add(this.parameters[i].getType().getScopedTypeNameEx(scope));\n if (i < paramLen - 1) {\n builder.add(MemberName.create(\", \"));\n }\n }\n\n if (this.hasVariableArgList) {\n builder.add(MemberName.create(\"...\" + this.parameters[i].name + \": \"));\n builder.add(this.parameters[i].getType().getScopedTypeNameEx(scope));\n }\n\n if (shortform) {\n if (brackets) {\n builder.add(MemberName.create(\"] => \"));\n }\n else {\n builder.add(MemberName.create(\") => \"));\n }\n }\n else {\n if (brackets) {\n builder.add(MemberName.create(\"]: \"));\n }\n else {\n builder.add(MemberName.create(\"): \"));\n }\n }\n\n if (this.returnType.type) {\n builder.add(this.returnType.type.getScopedTypeNameEx(scope));\n }\n else {\n builder.add(MemberName.create(\"any\"));\n }\n return builder;\n }\n }\n\n export class SignatureGroup {\n public signatures: Signature[] = [];\n public hasImplementation = true;\n public definitionSignature: Signature = null;\n public hasBeenTypechecked = false;\n public flags: SignatureFlags = SignatureFlags.None;\n public addSignature(signature: Signature) {\n if (this.signatures == null) {\n this.signatures = new Signature[];\n }\n this.signatures[this.signatures.length] = signature;\n \n // REVIEW: duplicates should be found within createFunctionSignature,\n // so we won't check for them here\n if (signature.declAST &&\n !signature.declAST.isOverload &&\n !signature.declAST.isSignature() && \n !hasFlag(signature.declAST.fncFlags, FncFlags.Ambient) &&\n hasFlag(signature.declAST.fncFlags, FncFlags.Definition)) {\n this.definitionSignature = signature;\n }\n }\n\n public toString() { return this.signatures.toString(); }\n public toStrings(prefix: string, shortform: bool, scope: SymbolScope) {\n var result : MemberName[] = []; \n var len = this.signatures.length;\n if (len > 1) {\n shortform = false;\n }\n for (var i = 0; i < len; i++) {\n // the definition signature shouldn't be printed if there are overloads\n if (len > 1 && this.signatures[i] == this.definitionSignature) {\n continue;\n }\n if (this.flags & SignatureFlags.IsIndexer) {\n result.push(this.signatures[i].toStringHelperEx(shortform, true, scope));\n }\n else {\n result.push(this.signatures[i].toStringHelperEx(shortform, false, scope, prefix));\n }\n }\n \n return result;\n }\n\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): SignatureGroup {\n var result = new SignatureGroup();\n if (this.signatures) {\n for (var i = 0, len = this.signatures.length; i < len; i++) {\n result.addSignature(this.signatures[i].specializeType(pattern, replacement, checker));\n }\n }\n return result;\n }\n\n // verifies that signatures are\n // - unique within a given group\n // - compatible with the declaration signature\n public verifySignatures(checker: TypeChecker) {\n\n var len = 0;\n \n // TODO: verify no signature pair with identical parameters\n if (this.signatures && ((len = this.signatures.length) > 0)) {\n \n for (var i = 0; i < len; i++) {\n \n for (var j = i + 1; j < len; j++) {\n // next check for equivalence between overloads - no two can be exactly the same \n if (this.signatures[i].declAST && this.signatures[j].declAST &&\n (!hasFlag(this.signatures[i].declAST.fncFlags, FncFlags.Definition) && !hasFlag(this.signatures[j].declAST.fncFlags, FncFlags.Definition)) &&\n checker.signaturesAreIdentical(this.signatures[i], this.signatures[j])) {\n checker.errorReporter.simpleError(this.signatures[i].declAST, (this.signatures[i].declAST && this.signatures[i].declAST.name) ? \"Signature for '\" + this.signatures[i].declAST.name.actualText + \"' is duplicated\" :\"Signature is duplicated\");\n }\n }\n \n // finally, ensure that the definition is assignable to each signature\n if (this.definitionSignature) {\n if (!checker.signatureIsAssignableToTarget(this.definitionSignature, this.signatures[i])) {\n checker.errorReporter.simpleError(this.signatures[i].declAST, \"Overload signature is not compatible with function definition\");\n }\n }\n }\n }\n }\n\n public typeCheck(checker: TypeChecker, ast: AST, hasConstruct:bool) {\n \n if (this.hasBeenTypechecked) {\n return;\n }\n \n // set here to prevent us from recursively invoking typeCheck again\n this.hasBeenTypechecked = true;\n \n var len = 0;\n \n if (this.signatures && ((len = this.signatures.length) > 0)) {\n \n // first, typecheck each signature\n for (var i = 0; i < len; i++) {\n\n if (!hasConstruct && !this.definitionSignature && this.signatures[i].declAST && this.signatures[i].declAST.isOverload && !hasFlag(this.signatures[i].declAST.fncFlags, FncFlags.Ambient)) {\n checker.errorReporter.simpleError(this.signatures[i].declAST, \"Overload declaration lacks definition\");\n }\n\n // If we're typechecking a constructor via one of its overloads, ensure that the outer class is typechecked, since we need to validate its inheritance properties\n // to properly check that 'super' is being used correctly\n if (this.signatures[i].declAST && this.signatures[i].declAST.isConstructor && this.signatures[i].declAST.classDecl && this.signatures[i].declAST.classDecl.type.symbol.typeCheckStatus == TypeCheckStatus.NotStarted) {\n checker.typeFlow.typeCheck(this.signatures[i].declAST.classDecl);\n }\n\n checker.typeFlow.typeCheck(this.signatures[i].declAST);\n }\n\n this.verifySignatures(checker);\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///<reference path='typescript.ts' />\n///<reference path='..\\harness\\external\\json2.ts' />\n\nmodule TypeScript {\n export class SourceMapPosition {\n public sourceLine: number;\n public sourceColumn: number;\n public emittedLine: number;\n public emittedColumn: number;\n }\n\n export class SourceMapping {\n public start = new SourceMapPosition();\n public end = new SourceMapPosition();\n public nameIndex: number = -1;\n public childMappings: SourceMapping[] = [];\n }\n\n export class SourceMapper {\n static MapFileExtension = \".map\";\n \n public sourceMappings: SourceMapping[] = [];\n public currentMappings: SourceMapping[][] = [];\n\n public names: string[] = [];\n public currentNameIndex: number[] = [];\n\n public jsFileName: string;\n public tsFileName: string;\n\n constructor(tsFileName: string, jsFileName: string, public jsFile: ITextWriter, public sourceMapOut: ITextWriter, public errorReporter: ErrorReporter) {\n this.currentMappings.push(this.sourceMappings);\n\n jsFileName = switchToForwardSlashes(jsFileName);\n this.jsFileName = TypeScript.getPrettyName(jsFileName, false, true);\n\n var removalIndex = jsFileName.lastIndexOf(this.jsFileName);\n var fixedPath = jsFileName.substring(0, removalIndex);\n\n this.tsFileName = TypeScript.getRelativePathToFixedPath(fixedPath, tsFileName);\n }\n \n // Generate source mapping\n static EmitSourceMapping(allSourceMappers: SourceMapper[]) {\n // At this point we know that there is at least one source mapper present.\n // If there are multiple source mappers, all will correspond to same map file but different sources\n\n // Output map file name into the js file\n var sourceMapper = allSourceMappers[0];\n sourceMapper.jsFile.WriteLine(\"//@ sourceMappingURL=\" + sourceMapper.jsFileName + SourceMapper.MapFileExtension);\n\n // Now output map file\n var sourceMapOut = sourceMapper.sourceMapOut;\n var mappingsString = \"\";\n var tsFiles: string[] = [];\n\n var prevEmittedColumn = 0;\n var prevEmittedLine = 0;\n var prevSourceColumn = 0;\n var prevSourceLine = 0;\n var prevSourceIndex = 0;\n var prevNameIndex = 0;\n var namesList: string[] = [];\n var namesCount = 0;\n var emitComma = false;\n\n var recordedPosition: SourceMapPosition = null;\n for (var sourceMapperIndex = 0; sourceMapperIndex < allSourceMappers.length; sourceMapperIndex++) {\n sourceMapper = allSourceMappers[sourceMapperIndex];\n\n // If there are any mappings generated\n var currentSourceIndex = tsFiles.length;\n tsFiles.push(sourceMapper.tsFileName);\n\n // Join namelist\n if (sourceMapper.names.length > 0) {\n namesList.push.apply(namesList, sourceMapper.names);\n }\n\n var recordSourceMapping = (mappedPosition: SourceMapPosition, nameIndex: number) => {\n if (recordedPosition != null &&\n recordedPosition.emittedColumn == mappedPosition.emittedColumn &&\n recordedPosition.emittedLine == mappedPosition.emittedLine) {\n // This position is already recorded\n return;\n }\n\n // Record this position\n if (prevEmittedLine !== mappedPosition.emittedLine) {\n while (prevEmittedLine < mappedPosition.emittedLine) {\n prevEmittedColumn = 0;\n mappingsString = mappingsString + \";\";\n prevEmittedLine++;\n }\n emitComma = false;\n }\n else if (emitComma) {\n mappingsString = mappingsString + \",\";\n }\n\n // 1. Relative Column\n mappingsString = mappingsString + Base64VLQFormat.encode(mappedPosition.emittedColumn - prevEmittedColumn);\n prevEmittedColumn = mappedPosition.emittedColumn;\n\n // 2. Relative sourceIndex \n mappingsString = mappingsString + Base64VLQFormat.encode(currentSourceIndex - prevSourceIndex);\n prevSourceIndex = currentSourceIndex;\n\n // 3. Relative sourceLine 0 based\n mappingsString = mappingsString + Base64VLQFormat.encode(mappedPosition.sourceLine - 1 - prevSourceLine);\n prevSourceLine = mappedPosition.sourceLine - 1;\n\n // 4. Relative sourceColumn 0 based \n mappingsString = mappingsString + Base64VLQFormat.encode(mappedPosition.sourceColumn - prevSourceColumn);\n prevSourceColumn = mappedPosition.sourceColumn;\n\n // 5. Relative namePosition 0 based\n if (nameIndex >= 0) {\n mappingsString = mappingsString + Base64VLQFormat.encode(namesCount + nameIndex - prevNameIndex);\n prevNameIndex = namesCount + nameIndex;\n }\n\n emitComma = true;\n recordedPosition = mappedPosition;\n }\n\n // Record starting spans\n var recordSourceMappingSiblings = (sourceMappings: SourceMapping[]) => {\n for (var i = 0; i < sourceMappings.length; i++) {\n var sourceMapping = sourceMappings[i];\n recordSourceMapping(sourceMapping.start, sourceMapping.nameIndex);\n recordSourceMappingSiblings(sourceMapping.childMappings);\n recordSourceMapping(sourceMapping.end, sourceMapping.nameIndex);\n }\n }\n\n recordSourceMappingSiblings(sourceMapper.sourceMappings, -1);\n namesCount = namesCount + sourceMapper.names.length;\n }\n\n // Write the actual map file\n if (mappingsString != \"\") {\n sourceMapOut.Write(JSON2.stringify({\n version: 3,\n file: sourceMapper.jsFileName,\n sources: tsFiles,\n names: namesList,\n mappings: mappingsString\n }));\n }\n\n // Done, close the file\n try {\n // Closing files could result in exceptions, report them if they occur\n sourceMapOut.Close();\n } catch (ex) {\n sourceMapper.errorReporter.emitterError(null, ex.message);\n }\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n // private members are private to the scope\n // public members are public to the scope\n export class ScopedMembers {\n\n public allMembers: IHashTable;\n public publicMembers: IHashTable;\n public privateMembers: IHashTable;\n\n constructor (public dualMembers: DualStringHashTable) { \n this.allMembers = this.dualMembers;\n this.publicMembers = this.dualMembers.primaryTable;\n this.privateMembers = this.dualMembers.secondaryTable;\n }\n\n // add a public member\n public addPublicMember(key: string, data) { return this.dualMembers.primaryTable.add(key, data); }\n\n // add a private member \n public addPrivateMember(key: string, data) { return this.dualMembers.secondaryTable.add(key, data); }\n }\n\n export enum SymbolKind {\n None,\n Type,\n Field,\n Parameter,\n Variable,\n }\n\n export class SymbolScope {\n constructor (public container: Symbol) { }\n public printLabel() { return \"base\"; }\n public getAllSymbolNames(members: bool): string[]{\n return [\"please\", \"implement\", \"in\", \"derived\", \"classes\"];\n }\n public getAllTypeSymbolNames(members: bool): string[]{\n return [\"please\", \"implement\", \"in\", \"derived\", \"classes\"];\n }\n public getAllValueSymbolNames(members: bool): string[]{\n return [\"please\", \"implement\", \"in\", \"derived\", \"classes\"];\n }\n // advanced search using a filter\n public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n // find in this immediate scope\n public findLocal(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n // find in value namespace \n public find(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n // find symbol that supplies an implementation\n public findImplementation(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n // restrict the search to ambient values\n public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n public print(outfile: ITextWriter) {\n if (this.container) {\n outfile.WriteLine(this.printLabel() + \" scope with container: \" + this.container.name + \"...\");\n }\n else {\n outfile.WriteLine(this.printLabel() + \" scope...\");\n }\n }\n\n public enter(container: Symbol, ast: AST, symbol: Symbol, errorReporter: ErrorReporter, publicOnly: bool,\n typespace: bool, ambient: bool): void {\n throw new Error(\"please implement in derived class\");\n }\n\n public getTable(): IHashTable {\n throw new Error(\"please implement in derived class\");\n }\n }\n\n function symbolCanBeUsed(sym: Symbol, publicOnly) {\n return publicOnly ? !(hasFlag(sym.flags, SymbolFlags.Private) ||\n (sym.declAST && sym.declAST.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>sym.declAST).fncFlags, FncFlags.Private)))\n : true;\n }\n\n export class SymbolAggregateScope extends SymbolScope {\n public printLabel() { return \"agg\"; }\n public valueCache: IHashTable = null;\n public valueImplCache: IHashTable = null;\n public valueAmbientCache: IHashTable = null;\n public typeCache: IHashTable = null;\n public typeImplCache: IHashTable = null;\n public typeAmbientCache: IHashTable = null;\n public parents: SymbolScope[] = null;\n public container: Symbol;\n\n constructor (container: Symbol) {\n super(container);\n this.container = container;\n }\n\n public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool) {\n if (this.parents) {\n for (var i = 0; i < this.parents.length; i++) {\n var sym = this.parents[i].search(filter, name, publicOnly, typespace);\n if (sym) {\n if (filter.update(sym)) {\n return sym;\n }\n }\n }\n }\n return filter.result;\n }\n\n public getAllSymbolNames(members: bool): string[]{\n var result: string[] = [];\n if (this.parents) {\n for (var i = 0; i < this.parents.length; i++) {\n var parentResult = this.parents[i].getAllSymbolNames(members);\n if (parentResult) {\n result = result.concat(parentResult);\n }\n }\n }\n return result;\n }\n\n public getAllTypeSymbolNames(members: bool): string[]{\n var result: string[] = [];\n if (this.parents) {\n for (var i = 0; i < this.parents.length; i++) {\n var parentResult = this.parents[i].getAllTypeSymbolNames(members);\n if (parentResult) {\n result = result.concat(parentResult);\n }\n }\n }\n return result;\n }\n\n public getAllValueSymbolNames(members: bool): string[]{\n var result: string[] = [];\n if (this.parents) {\n for (var i = 0; i < this.parents.length; i++) {\n var parentResult = this.parents[i].getAllValueSymbolNames(members);\n if (parentResult) {\n result = result.concat(parentResult);\n }\n }\n }\n return result;\n }\n\n public print(outfile: ITextWriter) {\n super.print(outfile);\n if (this.parents) {\n for (var i = 0; i < this.parents.length; i++) {\n this.parents[i].print(outfile);\n }\n }\n }\n\n public findImplementation(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym: Symbol = null;\n var i = 0;\n var implCache = this.valueImplCache;\n\n if (typespace) {\n implCache = this.typeImplCache;\n }\n if (implCache &&\n ((sym = implCache.lookup(name)) != null) &&\n (publicOnly ? !(hasFlag(sym.flags, SymbolFlags.Private) ||\n (sym.declAST && sym.declAST.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>sym.declAST).fncFlags, FncFlags.Private)))\n : true)) {\n return sym;\n }\n if (this.parents) {\n for (i = 0; i < this.parents.length; i++) {\n sym = this.parents[i].findImplementation(name, publicOnly, typespace);\n if (sym) {\n break;\n }\n }\n }\n if (implCache) {\n if (typespace) {\n this.typeImplCache = new StringHashTable();\n implCache = this.typeImplCache;\n }\n else {\n this.valueImplCache = new StringHashTable();\n implCache = this.valueImplCache;\n }\n }\n implCache.add(name, sym);\n return sym;\n }\n\n public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym: Symbol = null;\n var i = 0;\n var cache = this.valueCache;\n\n if (typespace) {\n cache = this.typeCache;\n }\n if (cache &&\n ((sym = cache.lookup(name)) != null) &&\n (publicOnly ? !(hasFlag(sym.flags, SymbolFlags.Private) ||\n (sym.declAST && sym.declAST.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>sym.declAST).fncFlags, FncFlags.Private)))\n : true)) {\n return sym;\n }\n if (this.parents) {\n for (i = 0; i < this.parents.length; i++) {\n sym = this.parents[i].find(name, publicOnly, typespace);\n if (sym) {\n break;\n }\n }\n }\n if (cache == null) {\n if (typespace) {\n this.typeCache = new StringHashTable();\n cache = this.typeCache;\n }\n else {\n this.valueCache = new StringHashTable();\n cache = this.valueCache;\n }\n }\n cache.add(name, sym);\n return sym;\n }\n\n public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym: Symbol = null;\n var i = 0;\n var cache = this.valueAmbientCache;\n if (typespace) {\n cache = this.typeAmbientCache;\n }\n if (cache && ((sym = cache.lookup(name)) != null)) {\n return sym;\n }\n if (this.parents) {\n for (i = 0; i < this.parents.length; i++) {\n sym = this.parents[i].findAmbient(name, publicOnly, typespace);\n if (sym) {\n break;\n }\n }\n }\n if (cache == null) {\n if (typespace) {\n this.typeAmbientCache = new StringHashTable();\n cache = this.typeAmbientCache;\n }\n else {\n this.valueAmbientCache = new StringHashTable();\n cache = this.valueAmbientCache;\n }\n }\n cache.add(name, sym);\n return sym;\n }\n\n public addParentScope(parent: SymbolScope): void {\n if (this.parents == null) {\n this.parents = new SymbolScope[];\n }\n this.parents[this.parents.length] = parent;\n }\n }\n\n export class SymbolTableScope extends SymbolScope {\n public container: Symbol;\n\n constructor(public valueMembers: ScopedMembers,\n public ambientValueMembers: ScopedMembers,\n public enclosedTypes: ScopedMembers,\n public ambientEnclosedTypes: ScopedMembers,\n container: Symbol)\n {\n super(container);\n this.container = container;\n }\n\n public printLabel() { return \"table\"; }\n\n public getAllSymbolNames(members: bool): string[]{\n var result = this.getAllTypeSymbolNames(members);\n\n return result.concat(this.getAllValueSymbolNames(members));\n }\n\n public getAllTypeSymbolNames(members: bool): string[]{\n var result = [];\n if (this.ambientEnclosedTypes) {\n result = result.concat(this.ambientEnclosedTypes.allMembers.getAllKeys());\n }\n if (this.enclosedTypes) {\n result = result.concat(this.enclosedTypes.allMembers.getAllKeys());\n }\n return result;\n }\n\n public getAllValueSymbolNames(members: bool): string[]{\n var result = [];\n if (this.ambientValueMembers) {\n result = result.concat(this.ambientValueMembers.allMembers.getAllKeys());\n }\n if (this.valueMembers) {\n result = result.concat(this.valueMembers.allMembers.getAllKeys());\n }\n return result;\n }\n\n public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool) {\n var sym = this.find(name, publicOnly, typespace);\n filter.update(sym);\n return filter.result;\n }\n\n public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n var table: IHashTable = null;\n var ambientTable: IHashTable = null;\n\n if (typespace) {\n table = (this.enclosedTypes == null) ? null :\n publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n ambientTable = (this.ambientEnclosedTypes == null) ? null :\n publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n }\n else {\n table = (this.valueMembers == null) ? null :\n publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n ambientTable = (this.ambientValueMembers == null) ? null :\n publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n }\n if (ambientTable) {\n var s = ambientTable.lookup(name);\n if (s) { return s; }\n }\n if (table) {\n var s = table.lookup(name);\n if (s) { return s; }\n }\n\n return null;\n }\n\n public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol {\n var ambientTable = (this.ambientValueMembers == null) ? null :\n publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n if (typespace) {\n ambientTable = (this.ambientEnclosedTypes == null) ? null :\n publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n }\n if (ambientTable) {\n var s = ambientTable.lookup(name);\n if (s) { return s; }\n }\n\n return null;\n }\n\n public print(outfile: ITextWriter) {\n super.print(outfile);\n if (this.ambientValueMembers) {\n this.ambientValueMembers.allMembers.map(function (key, sym, context) {\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.valueMembers) {\n this.valueMembers.allMembers.map(function (key, sym, context) {\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.ambientEnclosedTypes) {\n this.ambientEnclosedTypes.allMembers.map(function (key, sym, context) {\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.enclosedTypes) {\n this.enclosedTypes.allMembers.map(function (key, sym, context) {\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n }\n\n public findImplementation(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym = this.find(name, publicOnly, typespace);\n if (sym) {\n if (sym.kind() == SymbolKind.Type) {\n var typeSym = <TypeSymbol>sym;\n if (!typeSym.type.hasImplementation()) {\n sym = null;\n }\n }\n else if (sym.container) {\n if (sym.container.kind() == SymbolKind.Type) {\n var ctypeSym = <TypeSymbol>sym.container;\n if (!ctypeSym.type.hasImplementation()) {\n sym = null;\n }\n }\n }\n }\n return sym;\n }\n\n public getTable() {\n return this.valueMembers.publicMembers;\n }\n }\n\n export class SymbolScopeBuilder extends SymbolScope {\n public container: Symbol;\n \n constructor (public valueMembers: ScopedMembers,\n public ambientValueMembers: ScopedMembers,\n public enclosedTypes: ScopedMembers,\n public ambientEnclosedTypes: ScopedMembers,\n public parent: SymbolScope,\n container: Symbol)\n {\n super(container);\n this.container = container;\n }\n\n public printLabel() { return \"builder\"; }\n public getAllSymbolNames(members: bool): string[]{\n var result: string[] = this.getAllTypeSymbolNames(members);\n return result.concat(this.getAllValueSymbolNames(members));\n }\n\n public getAllTypeSymbolNames(members: bool): string[]{\n var result: string[] = [];\n if (this.ambientEnclosedTypes) {\n result = result.concat(this.ambientEnclosedTypes.allMembers.getAllKeys());\n }\n if (this.enclosedTypes) {\n result = result.concat(this.enclosedTypes.allMembers.getAllKeys());\n }\n if (!members && this.parent) {\n var parentResult = this.parent.getAllTypeSymbolNames(members);\n if (parentResult) {\n result = result.concat(parentResult);\n }\n }\n return result;\n }\n\n public getAllValueSymbolNames(members: bool): string[]{\n var result: string[] = [];\n if (this.ambientValueMembers) {\n result = result.concat(this.ambientValueMembers.allMembers.getAllKeys());\n }\n if (this.valueMembers) {\n result = result.concat(this.valueMembers.allMembers.getAllKeys());\n }\n if (!members && this.parent) {\n var parentResult = this.parent.getAllValueSymbolNames(members);\n if (parentResult) {\n result = result.concat(parentResult);\n }\n }\n return result;\n }\n\n public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool) {\n var sym: Symbol = null;\n var table = (this.valueMembers == null) ? null :\n publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n var ambientTable = (this.ambientValueMembers == null) ? null :\n publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n if (typespace) {\n table = (this.enclosedTypes == null) ? null :\n publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n ambientTable = (this.ambientEnclosedTypes == null) ? null :\n publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n }\n if (ambientTable) {\n if ((sym = ambientTable.lookup(name)) != null) {\n if (filter.update(sym)) {\n return sym;\n }\n }\n }\n if (table) {\n if ((sym = table.lookup(name)) != null) {\n if (filter.update(sym)) {\n return sym;\n }\n }\n }\n if (this.parent) {\n sym = this.parent.search(filter, name, publicOnly, typespace);\n if (sym) {\n if (filter.update(sym)) {\n return sym;\n }\n }\n }\n return filter.result;\n }\n\n public print(outfile: ITextWriter) {\n super.print(outfile);\n if (this.ambientValueMembers) {\n this.ambientValueMembers.allMembers.map(function (key, s, context) {\n var sym = <Symbol>s;\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.valueMembers) {\n this.valueMembers.allMembers.map(function (key, s, context) {\n var sym = <Symbol>s;\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.ambientEnclosedTypes) {\n this.ambientEnclosedTypes.allMembers.map(function (key, s, context) {\n var sym = <Symbol>s;\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.enclosedTypes) {\n this.enclosedTypes.allMembers.map(function (key, s, context) {\n var sym = <Symbol>s;\n outfile.WriteLine(\" \" + key);\n }, null);\n }\n if (this.parent) {\n this.parent.print(outfile);\n }\n }\n\n public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym: Symbol = null;\n var table = (this.valueMembers == null) ? null :\n publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n var ambientTable = (this.ambientValueMembers == null) ? null :\n publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n if (typespace) {\n table = (this.enclosedTypes == null) ? null :\n publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n ambientTable = (this.ambientEnclosedTypes == null) ? null :\n publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n }\n if (ambientTable && ((sym = ambientTable.lookup(name)) != null)) {\n return sym;\n }\n if (table && ((sym = table.lookup(name)) != null)) {\n return sym;\n }\n if (this.parent) {\n return this.parent.find(name, publicOnly, typespace);\n }\n return null;\n }\n\n public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym: Symbol = null;\n var ambientTable = (this.ambientValueMembers == null) ? null :\n publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n if (typespace) {\n ambientTable = (this.ambientEnclosedTypes == null) ? null :\n publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n }\n if (ambientTable && ((sym = ambientTable.lookup(name)) != null)) {\n return sym;\n }\n if (this.parent) {\n return this.parent.findAmbient(name, publicOnly, typespace);\n }\n return null;\n }\n\n public findLocal(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym: Symbol = null;\n var table = (this.valueMembers == null) ? null :\n publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n var ambientTable = (this.ambientValueMembers == null) ? null :\n publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n if (typespace) {\n table = (this.enclosedTypes == null) ? null :\n publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n ambientTable = (this.ambientEnclosedTypes == null) ? null :\n publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n }\n if (table) {\n if ((sym = table.lookup(name)) != null) {\n if (sym) { return sym; }\n }\n }\n if (ambientTable) {\n if ((sym = ambientTable.lookup(name)) != null) {\n if (sym) { return sym; }\n }\n }\n return null;\n }\n\n public enter(container: Symbol, ast: AST, symbol: Symbol, errorReporter: ErrorReporter, insertAsPublic: bool, typespace: bool, ambient: bool): void {\n var table = null;\n\n if (ambient) {\n if (typespace) {\n table = (this.ambientEnclosedTypes == null) ? null :\n insertAsPublic ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.privateMembers;\n }\n else {\n table = (this.ambientValueMembers == null) ? null :\n insertAsPublic ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.privateMembers;\n }\n }\n else {\n if (typespace) {\n table = (this.enclosedTypes == null) ? null :\n insertAsPublic ? this.enclosedTypes.publicMembers : this.enclosedTypes.privateMembers;\n }\n else {\n table = (this.valueMembers == null) ? null :\n insertAsPublic ? this.valueMembers.publicMembers : this.valueMembers.privateMembers;\n }\n }\n\n if (table) {\n if (!table.add(symbol.name, symbol)) {\n errorReporter.duplicateIdentifier(ast, symbol.name);\n }\n }\n else {\n CompilerDiagnostics.Alert(\"YYYYY\"); // REVIEW: Surely we can do better than this...\n }\n symbol.container = container;\n }\n\n public getTable() { return this.valueMembers.allMembers; }\n }\n\n export class FilteredSymbolScope extends SymbolScope {\n constructor (public scope: SymbolScope, container: Symbol, public filter: ScopeSearchFilter) {\n super(container);\n }\n public print(outfile: ITextWriter) {\n this.scope.print(outfile);\n }\n\n public find(name: string, publicOnly: bool, typespace: bool) {\n this.filter.reset();\n return this.scope.search(this.filter, name, publicOnly, typespace);\n }\n public findLocal(name: string, publicOnly: bool, typespace: bool) { return this.scope.findLocal(name, publicOnly, typespace); }\n }\n\n export class FilteredSymbolScopeBuilder extends SymbolScopeBuilder {\n constructor (valueMembers: ScopedMembers, parent: SymbolScope, container: Symbol, public filter: (sym: Symbol) =>bool) {\n super(valueMembers, null, null, null, parent, container);\n }\n public findLocal(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym = super.findLocal(name, publicOnly, typespace);\n if (sym) {\n if (!this.filter(sym)) {\n return null;\n }\n }\n return sym;\n }\n\n public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool):Symbol {\n throw new Error(\"please implement\");\n }\n\n public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n var sym = super.findLocal(name, publicOnly, typespace);\n if (sym) {\n if (!this.filter(sym)) {\n return null;\n }\n }\n return super.find(name, publicOnly, typespace);\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export enum TypeCheckStatus {\n NotStarted,\n Started,\n Finished,\n }\n\n // For lexically-scoped constructs\n export function aLexicallyEnclosesB(a: Symbol, b: Symbol) {\n if (a.declAST && b && b.declAST && a.declAST.nodeType == NodeType.FuncDecl) {\n return a.declAST.minChar <= b.declAST.minChar && a.declAST.limChar >= b.declAST.limChar;\n }\n else {\n return false;\n }\n }\n\n export function aEnclosesB(a: Symbol, b: Symbol) {\n while (a.container) {\n if (a == b || aLexicallyEnclosesB(a.container, b)) {\n return true;\n }\n a = a.container;\n }\n return false;\n }\n\n export interface PhasedTypecheckObject {\n typeCheckStatus: TypeCheckStatus;\n }\n\n export class Symbol {\n public bound = false;\n public container: Symbol;\n public instanceScope(): SymbolScope { return null; }\n public isVariable() { return false; }\n public isMember() { return false; }\n public isInferenceSymbol() { return false; }\n public isWith() { return false; }\n public writeable() { return false; }\n public isType(): bool { return false; }\n public getType(): Type { return null; }\n public flags: SymbolFlags = SymbolFlags.None;\n public refs: Identifier[];\n public isAccessor() { return false; }\n public isObjectLitField = false;\n\n public declAST: AST = null;\n public declModule: ModuleDeclaration = null; // if child of module, this is the module that declared it\n\n public passSymbolCreated: number = CompilerDiagnostics.analysisPass;\n\n constructor(public name: string, public location: number, public length: number,\n public unitIndex: number) { }\n\n public isInstanceProperty() {\n return hasFlag(this.flags, SymbolFlags.Property) && (!hasFlag(this.flags, SymbolFlags.ModuleMember));\n }\n\n public getTypeName(scope: SymbolScope): string {\n return this.getTypeNameEx(scope).toString();\n }\n \n public getTypeNameEx(scope: SymbolScope): MemberName {\n return MemberName.create(this.toString());\n }\n\n public getOptionalNameString() {\n return hasFlag(this.flags, SymbolFlags.Optional) ? \"?\" : \"\";\n }\n\n public pathToRoot() {\n var path = new Symbol[];\n var node = this;\n while (node && (node.name != globalId)) {\n path[path.length] = node;\n node = node.container;\n }\n return path;\n }\n\n public findCommonAncestorPath(b: Symbol) {\n if (this.container == null) {\n return new Symbol[];\n }\n var aPath = this.container.pathToRoot();\n var bPath: Symbol[];\n if (b) {\n bPath = b.pathToRoot();\n }\n else {\n bPath = new Symbol[];\n }\n var commonNodeIndex = -1;\n for (var i = 0, aLen = aPath.length; i < aLen; i++) {\n var aNode = aPath[i];\n for (var j = 0, bLen = bPath.length; j < bLen; j++) {\n var bNode = bPath[j];\n if (aNode == bNode) {\n commonNodeIndex = i;\n break;\n }\n }\n if (commonNodeIndex >= 0) {\n break;\n }\n }\n if (commonNodeIndex >= 0) {\n return aPath.slice(0, commonNodeIndex);\n }\n else {\n return aPath;\n }\n }\n\n // Gets the pretty Name for the symbol withing the scope\n public getPrettyName(scopeSymbol: Symbol) {\n return this.name;\n }\n\n public scopeRelativeName(scope: SymbolScope): string {\n if (scope == null) {\n return this.getPrettyName(null) + this.getOptionalNameString();\n }\n var lca = this.findCommonAncestorPath(scope.container);\n var builder = \"\";\n for (var i = 0, len = lca.length; i < len; i++) {\n var prettyName = lca[i].getPrettyName(i == len - 1 ? scope.container : lca[i + 1]);\n builder = prettyName + \".\" + builder;\n }\n builder += this.getPrettyName(len == 0 ? scope.container : lca[0]) + this.getOptionalNameString();\n return builder;\n }\n\n public fullName(): string {\n var builder = this.name;\n var ancestor = this.container;\n while (ancestor && (ancestor.name != globalId)) {\n builder = ancestor.name + \".\" + builder;\n ancestor = ancestor.container;\n }\n return builder;\n }\n\n public isExternallyVisible(checker: TypeChecker) {\n // Global module is not hidden\n if (this == checker.gloMod) {\n return true;\n }\n\n // private symbol\n if (hasFlag(this.flags, SymbolFlags.Private)) {\n return false;\n }\n\n // If the current container is not exported\n // If its in global - it is visible, otherwise it isn't\n if (!hasFlag(this.flags, SymbolFlags.Exported)) {\n return this.container == checker.gloMod;\n }\n\n // It is visible if its container is visible too\n return this.container.isExternallyVisible(checker);\n }\n\n public visible(scope: SymbolScope, checker: TypeChecker) {\n if (checker == null || this.container == checker.gloMod) {\n return true;\n }\n\n if (hasFlag(this.flags, SymbolFlags.ModuleMember)) {\n\n if (hasFlag(this.flags, SymbolFlags.Exported)) {\n if (!hasFlag(this.flags, SymbolFlags.Private)) {\n return true;\n }\n else {\n return aEnclosesB(this, scope.container);\n }\n }\n else {\n // REVIEW:\n // Note that in the scope-assignment and binding phases,\n // currentModDecl will point to the \"master\" module decl,\n // and not necessarily the one that the symbol in question\n // was declared in.\n // That's ok - there's no harm done in attributing the symbol\n // to the master mod decl in either of those phases, so long\n // as we reference the actual module fragment of declaration\n // during typecheck. Doing this also prevents us from printing\n // multiple error messages if the symbol is not visible.\n return checker && (checker.currentModDecl == this.declModule) ||\n (checker.currentModDecl &&\n checker.currentModDecl.mod &&\n checker.currentModDecl.mod.symbol &&\n this.declModule &&\n this.declModule.mod &&\n this.declModule.mod.symbol &&\n aEnclosesB(checker.currentModDecl.mod.symbol, this.declModule.mod.symbol));\n }\n }\n else {\n // field or method\n var isFunction = this.declAST && this.declAST.nodeType == NodeType.FuncDecl;\n var isMethod = isFunction && (<FuncDecl>this.declAST).isMethod();\n var isStaticFunction = isFunction && hasFlag((<FuncDecl>this.declAST).fncFlags, FncFlags.Static)\n var isPrivateMethod = isMethod && hasFlag((<FuncDecl>this.declAST).fncFlags, FncFlags.Private);\n var isAlias = this.isType() && (<TypeSymbol>this).aliasLink;\n\n if (this.isMember() || isMethod || isStaticFunction || isAlias) {\n if (hasFlag(this.flags, SymbolFlags.Private) || isPrivateMethod) {\n if (scope.container == null && this.container != scope.container) {\n return false; // it's an inner member being accessed by the global scope\n }\n else {\n return this.container == null ? true : aEnclosesB(scope.container, this.container);\n }\n }\n else {\n return true;\n }\n }\n else if (this.container) {\n return aEnclosesB(this, scope.container);\n }\n else {\n return true;\n }\n }\n }\n\n public addRef(identifier: Identifier) {\n if (!this.refs) {\n this.refs = [];\n }\n this.refs[this.refs.length] = identifier;\n }\n\n public toString() {\n if (this.name) {\n return this.name;\n }\n else {\n return \"_anonymous\";\n }\n }\n\n public print(outfile) {\n outfile.Write(this.toString());\n }\n\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n throw new Error(\"please implement in derived class\");\n }\n\n public setType(type: Type) {\n throw new Error(\"please implement in derived class\");\n }\n\n public kind(): SymbolKind {\n throw new Error(\"please implement in derived class\");\n }\n\n public getInterfaceDeclFromSymbol(checker: TypeChecker) {\n if (this.declAST != null) {\n if (this.declAST.nodeType == NodeType.InterfaceDeclaration) {\n return <InterfaceDeclaration>this.declAST;\n } else if (this.container != null && this.container != checker.gloMod && this.container.declAST.nodeType == NodeType.InterfaceDeclaration) {\n return <InterfaceDeclaration>this.container.declAST;\n }\n }\n\n return null;\n }\n\n public getVarDeclFromSymbol() {\n if (this.declAST != null && this.declAST.nodeType == NodeType.VarDecl) {\n return <VarDecl>this.declAST;\n }\n\n return null;\n }\n\n public getDocComments() : Comment[] {\n if (this.declAST != null) {\n return this.declAST.getDocComments();\n }\n\n return [];\n }\n\n public isStatic() {\n return hasFlag(this.flags, SymbolFlags.Static);\n }\n }\n\n export class ValueLocation {\n public symbol: Symbol;\n public typeLink: TypeLink;\n }\n\n export class InferenceSymbol extends Symbol {\n constructor (name: string, location: number, length: number, unitIndex: number) {\n super(name, location, length, unitIndex);\n }\n\n public typeCheckStatus = TypeCheckStatus.NotStarted;\n public isInferenceSymbol() { return true; }\n public transferVarFlags(varFlags: VarFlags) {\n if (hasFlag(varFlags, VarFlags.Ambient)) {\n this.flags |= SymbolFlags.Ambient;\n }\n if (hasFlag(varFlags, VarFlags.Constant)) {\n this.flags |= SymbolFlags.Constant;\n }\n if (hasFlag(varFlags, VarFlags.Static)) {\n this.flags |= SymbolFlags.Static;\n }\n if (hasFlag(varFlags, VarFlags.Property)) {\n this.flags |= SymbolFlags.Property;\n }\n if (hasFlag(varFlags, VarFlags.Private)) {\n this.flags |= SymbolFlags.Private;\n }\n if (hasFlag(varFlags, VarFlags.Public)) {\n this.flags |= SymbolFlags.Public;\n }\n if (hasFlag(varFlags, VarFlags.Readonly)) {\n this.flags |= SymbolFlags.Readonly;\n }\n if (hasFlag(varFlags, VarFlags.Exported)) {\n this.flags |= SymbolFlags.Exported;\n }\n }\n }\n\n export class TypeSymbol extends InferenceSymbol {\n public additionalLocations: number[];\n public expansions: Type[] = []; // For types that may be \"split\", keep track of the subsequent definitions\n public expansionsDeclAST: AST[] = [];\n public isDynamic = false;\n\n constructor (locName: string, location: number, length: number, unitIndex: number, public type: Type) {\n super(locName, location, length, unitIndex);\n this.prettyName = this.name;\n }\n\n public addLocation(loc: number) {\n if (this.additionalLocations == null) {\n this.additionalLocations = [];\n }\n this.additionalLocations[this.additionalLocations.length] = loc;\n }\n public isMethod = false;\n public aliasLink:ImportDeclaration = null;\n public kind() { return SymbolKind.Type; }\n public isType(): bool { return true; }\n public getType() { return this.type; }\n public prettyName: string;\n public onlyReferencedAsTypeRef = optimizeModuleCodeGen;\n\n public getTypeNameEx(scope: SymbolScope) {\n return this.type.getMemberTypeNameEx(this.name ? this.name + this.getOptionalNameString() : \"\", false, false, scope);\n }\n\n public instanceScope(): SymbolScope {\n // Don't use the constructor scope for a class body or methods - use the contained scope\n if (!(this.type.typeFlags & TypeFlags.IsClass) && this.type.isClass()) {\n return this.type.instanceType.constructorScope;\n }\n else {\n return this.type.containedScope;\n }\n }\n // corresponding instance type if this is a class\n public instanceType: Type;\n\n public toString() {\n var result = this.type.getTypeName();\n if (this.name) {\n result = this.name + \":\" + result;\n }\n return result;\n }\n\n public isClass() { return this.instanceType != null; }\n public isFunction() { return this.declAST != null && this.declAST.nodeType == NodeType.FuncDecl; }\n\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n if (this.type == pattern) {\n return replacement.symbol;\n }\n else {\n var replType = this.type.specializeType(pattern, replacement, checker, false);\n if (replType != this.type) {\n var result = new TypeSymbol(this.name, -1, 0, -1, replType);\n return result;\n }\n else {\n return this;\n }\n }\n }\n\n // Gets the pretty name of the symbol with respect to symbol of the scope (scopeSymbol)\n // searchTillRoot specifies if the name need to searched in the root path of the scope\n public getPrettyName(scopeSymbol: Symbol) {\n if (!!scopeSymbol && isQuoted(this.prettyName) && this.type.isModuleType()) {\n // Its a dynamic module - and need to be specialized with the scope\n // Check in exported module members in each scope\n var symbolPath = scopeSymbol.pathToRoot();\n var prettyName = this.getPrettyNameOfDynamicModule(symbolPath);\n if (prettyName != null) {\n return prettyName.name;\n }\n }\n\n return this.prettyName;\n }\n\n public getPrettyNameOfDynamicModule(scopeSymbolPath: Symbol[]) {\n var scopeSymbolPathLength = scopeSymbolPath.length;\n var externalSymbol: { name: string; symbol: Symbol; } = null;\n if (scopeSymbolPath.length > 0 &&\n scopeSymbolPath[scopeSymbolPathLength - 1].getType().isModuleType() &&\n (<TypeSymbol>scopeSymbolPath[scopeSymbolPathLength - 1]).isDynamic) {\n\n // Check if submodule is dynamic\n if (scopeSymbolPathLength > 1 &&\n scopeSymbolPath[scopeSymbolPathLength - 2].getType().isModuleType() &&\n (<TypeSymbol>scopeSymbolPath[scopeSymbolPathLength - 2]).isDynamic) {\n var moduleType = <ModuleType>scopeSymbolPath[scopeSymbolPathLength - 2].getType();\n externalSymbol = moduleType.findDynamicModuleName(this.type);\n\n }\n\n if (externalSymbol == null) {\n // Check in this module\n var moduleType = <ModuleType>scopeSymbolPath[scopeSymbolPathLength - 1].getType();\n externalSymbol = moduleType.findDynamicModuleName(this.type);\n }\n }\n\n return externalSymbol;\n }\n\n public getDocComments(): Comment[]{\n var comments : Comment[] = [];\n if (this.declAST != null) {\n comments = comments.concat(this.declAST.getDocComments());\n }\n\n for (var i = 0; i < this.expansionsDeclAST.length; i++) {\n comments = comments.concat(this.expansionsDeclAST[i].getDocComments());\n }\n\n return comments;\n }\n }\n\n export class WithSymbol extends TypeSymbol {\n constructor (location: number, unitIndex: number, withType: Type) {\n super(\"with\", location, 4, unitIndex, withType);\n }\n public isWith() { return true; }\n }\n\n export class FieldSymbol extends InferenceSymbol {\n public name: string;\n public location: number;\n\n constructor (name: string, location: number, unitIndex: number, public canWrite: bool,\n public field: ValueLocation) {\n\n super(name, location, name.length, unitIndex);\n this.name = name;\n this.location = location;\n }\n public kind() { return SymbolKind.Field; }\n public writeable() { return this.isAccessor() ? this.setter != null : this.canWrite; }\n public getType() { return this.field.typeLink.type; }\n public getTypeNameEx(scope: SymbolScope) {\n return MemberName.create(this.field.typeLink.type.getScopedTypeNameEx(scope), this.name + this.getOptionalNameString() + \": \", \"\");\n }\n\n public isMember() { return true; }\n public setType(type: Type) {\n this.field.typeLink.type = type;\n }\n\n public getter: TypeSymbol = null;\n public setter: TypeSymbol = null;\n public hasBeenEmitted = false; // since getters and setters are emitted together, need to track if one has been emitted\n\n public isAccessor() { return this.getter != null || this.setter != null; }\n\n public isVariable() { return true; }\n public toString() { return this.getTypeNameEx(null).toString(); }\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n var rType = this.field.typeLink.type.specializeType(pattern, replacement, checker, false);\n if (rType != this.field.typeLink.type) {\n var fieldDef = new ValueLocation();\n var result = new FieldSymbol(this.name, 0, checker.locationInfo.unitIndex,\n this.canWrite, fieldDef);\n result.flags = this.flags;\n fieldDef.symbol = result;\n fieldDef.typeLink = new TypeLink();\n result.setType(rType);\n result.typeCheckStatus = TypeCheckStatus.Finished;\n return result;\n }\n else {\n return this;\n }\n }\n\n public getDocComments(): Comment[] {\n if (this.getter != null || this.setter != null) {\n var comments : Comment[] = [];\n if (this.getter != null) {\n comments = comments.concat(this.getter.getDocComments());\n }\n if (this.setter != null) {\n comments = comments.concat(this.setter.getDocComments());\n }\n return comments;\n }\n else if (this.declAST != null) {\n return this.declAST.getDocComments();\n }\n\n return [];\n }\n\n }\n\n export class ParameterSymbol extends InferenceSymbol {\n public name: string;\n public location: number;\n private paramDocComment: string = null;\n public funcDecl: AST = null;\n \n constructor (name: string, location: number, unitIndex: number,\n public parameter: ValueLocation) {\n super(name, location, name.length, unitIndex);\n\n this.name = name;\n this.location = location;\n }\n public kind() { return SymbolKind.Parameter; }\n public writeable() { return true; }\n public getType() { return this.parameter.typeLink.type; }\n public setType(type: Type) {\n this.parameter.typeLink.type = type;\n }\n public isVariable() { return true; }\n public argsOffset = (-1);\n public isOptional() {\n if (this.parameter && this.parameter.symbol && this.parameter.symbol.declAST) {\n return (<ArgDecl>this.parameter.symbol.declAST).isOptional;\n }\n else {\n return false;\n }\n }\n\n public getTypeNameEx(scope: SymbolScope) {\n return MemberName.create(this.getType().getScopedTypeNameEx(scope), this.name + (this.isOptional() ? \"?\" : \"\") + \": \", \"\");\n }\n\n public toString() { return this.getTypeNameEx(null).toString(); }\n\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n var rType = this.parameter.typeLink.type.specializeType(pattern, replacement, checker, false);\n if (this.parameter.typeLink.type != rType) {\n var paramDef = new ValueLocation();\n var result = new ParameterSymbol(this.name, 0, checker.locationInfo.unitIndex,\n paramDef);\n paramDef.symbol = result;\n result.setType(rType);\n return result;\n }\n else {\n return this;\n }\n }\n\n public getParameterDocComments() {\n if (!this.paramDocComment) {\n var parameterComments: string[] = [];\n if (this.funcDecl) {\n var fncDocComments = this.funcDecl.getDocComments();\n var paramComment = Comment.getParameterDocCommentText(this.name, fncDocComments);\n if (paramComment != \"\") {\n parameterComments.push(paramComment);\n }\n }\n var docComments = TypeScript.Comment.getDocCommentText(this.getDocComments());\n if (docComments != \"\") {\n parameterComments.push(docComments);\n }\n \n this.paramDocComment = parameterComments.join(\"\\n\");\n }\n\n return this.paramDocComment;\n }\n }\n\n export class VariableSymbol extends InferenceSymbol {\n\n constructor (name: string, location: number, unitIndex: number, public variable: ValueLocation) {\n super(name, location, name.length, unitIndex);\n }\n public kind() { return SymbolKind.Variable; }\n public writeable() { return true; }\n public getType() { return this.variable.typeLink.type; }\n public getTypeNameEx(scope: SymbolScope) {\n return MemberName.create(this.getType().getScopedTypeNameEx(scope), this.name + \": \", \"\");\n }\n\n public setType(type: Type) {\n this.variable.typeLink.type = type;\n }\n public isVariable() { 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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export enum TokenID {\n // Keywords\n Any,\n Bool,\n Break,\n Case,\n Catch,\n Class,\n Const,\n Continue,\n Debugger,\n Default,\n Delete,\n Do,\n Else,\n Enum,\n Export,\n Extends,\n Declare,\n False,\n Finally,\n For,\n Function,\n Constructor,\n Get,\n If,\n Implements,\n Import,\n In,\n InstanceOf,\n Interface,\n Let,\n Module,\n New,\n Number,\n Null,\n Package,\n Private,\n Protected,\n Public,\n Return,\n Set,\n Static,\n String,\n Super,\n Switch,\n This,\n Throw,\n True,\n Try,\n TypeOf,\n Var,\n Void,\n With,\n While,\n Yield,\n // Punctuation\n Semicolon,\n OpenParen,\n CloseParen,\n OpenBracket,\n CloseBracket,\n OpenBrace,\n CloseBrace,\n Comma,\n Equals,\n PlusEquals,\n MinusEquals,\n AsteriskEquals,\n SlashEquals,\n PercentEquals,\n AmpersandEquals,\n CaretEquals,\n BarEquals,\n LessThanLessThanEquals,\n GreaterThanGreaterThanEquals,\n GreaterThanGreaterThanGreaterThanEquals,\n Question,\n Colon,\n BarBar,\n AmpersandAmpersand,\n Bar,\n Caret,\n And,\n EqualsEquals,\n ExclamationEquals,\n EqualsEqualsEquals,\n ExclamationEqualsEquals,\n LessThan,\n LessThanEquals,\n GreaterThan,\n GreaterThanEquals,\n LessThanLessThan,\n GreaterThanGreaterThan,\n GreaterThanGreaterThanGreaterThan,\n Plus,\n Minus,\n Asterisk,\n Slash,\n Percent,\n Tilde,\n Exclamation,\n PlusPlus,\n MinusMinus,\n Dot,\n DotDotDot,\n Error,\n EndOfFile,\n EqualsGreaterThan,\n Identifier,\n StringLiteral,\n RegularExpressionLiteral,\n NumberLiteral,\n Whitespace,\n Comment,\n Lim,\n LimFixed = EqualsGreaterThan,\n LimKeyword = Yield,\n }\n\n export var tokenTable = new TokenInfo[];\n export var nodeTypeTable = new string[];\n export var nodeTypeToTokTable = new number[];\n export var noRegexTable = new bool[];\n\n noRegexTable[TokenID.Identifier] = true;\n noRegexTable[TokenID.StringLiteral] = true;\n noRegexTable[TokenID.NumberLiteral] = true;\n noRegexTable[TokenID.RegularExpressionLiteral] = true;\n noRegexTable[TokenID.This] = true;\n noRegexTable[TokenID.PlusPlus] = true;\n noRegexTable[TokenID.MinusMinus] = true;\n noRegexTable[TokenID.CloseParen] = true;\n noRegexTable[TokenID.CloseBracket] = true;\n noRegexTable[TokenID.CloseBrace] = true;\n noRegexTable[TokenID.True] = true;\n noRegexTable[TokenID.False] = true;\n\n export enum OperatorPrecedence {\n None,\n Comma,\n Assignment,\n Conditional,\n LogicalOr,\n LogicalAnd,\n BitwiseOr,\n BitwiseExclusiveOr,\n BitwiseAnd,\n Equality,\n Relational,\n Shift,\n Additive,\n Multiplicative,\n Unary,\n Lim\n }\n\n export enum Reservation {\n None = 0,\n Javascript = 1,\n JavascriptFuture = 2,\n TypeScript = 4,\n JavascriptFutureStrict = 8,\n TypeScriptAndJS = Javascript | TypeScript,\n TypeScriptAndJSFuture = JavascriptFuture | TypeScript,\n TypeScriptAndJSFutureStrict = JavascriptFutureStrict | TypeScript,\n }\n\n export class TokenInfo {\n constructor (public tokenId: TokenID, public reservation: Reservation,\n public binopPrecedence: number, public binopNodeType: number,\n public unopPrecedence: number, public unopNodeType: number,\n public text: string, public ers: ErrorRecoverySet) { }\n }\n\n function setTokenInfo(tokenId: TokenID, reservation: number, binopPrecedence: number,\n binopNodeType: number, unopPrecedence: number, unopNodeType: number,\n text: string, ers: ErrorRecoverySet) {\n if (tokenId !== undefined) {\n tokenTable[tokenId] = new TokenInfo(tokenId, reservation, binopPrecedence,\n binopNodeType, unopPrecedence, unopNodeType, text, ers);\n if (binopNodeType != NodeType.None) {\n nodeTypeTable[binopNodeType] = text;\n nodeTypeToTokTable[binopNodeType] = tokenId;\n }\n if (unopNodeType != NodeType.None) {\n nodeTypeTable[unopNodeType] = text;\n }\n }\n }\n\n setTokenInfo(TokenID.Any, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"any\", ErrorRecoverySet.PrimType);\n setTokenInfo(TokenID.Bool, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"bool\", ErrorRecoverySet.PrimType);\n setTokenInfo(TokenID.Break, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"break\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Case, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"case\", ErrorRecoverySet.SCase);\n setTokenInfo(TokenID.Catch, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"catch\", ErrorRecoverySet.Catch);\n setTokenInfo(TokenID.Class, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"class\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.Const, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"const\", ErrorRecoverySet.Var);\n setTokenInfo(TokenID.Continue, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"continue\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Debugger, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.Debugger, \"debugger\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Default, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"default\", ErrorRecoverySet.SCase);\n setTokenInfo(TokenID.Delete, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Delete, \"delete\", ErrorRecoverySet.Prefix);\n setTokenInfo(TokenID.Do, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"do\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Else, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"else\", ErrorRecoverySet.Else);\n setTokenInfo(TokenID.Enum, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"enum\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.Export, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"export\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.Extends, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"extends\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.Declare, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"declare\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.False, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"false\", ErrorRecoverySet.RLit);\n setTokenInfo(TokenID.Finally, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"finally\", ErrorRecoverySet.Catch);\n setTokenInfo(TokenID.For, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"for\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Function, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"function\", ErrorRecoverySet.Func);\n setTokenInfo(TokenID.Constructor, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"constructor\", ErrorRecoverySet.Func);\n setTokenInfo(TokenID.Get, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"get\", ErrorRecoverySet.Func);\n setTokenInfo(TokenID.Set, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"set\", ErrorRecoverySet.Func);\n setTokenInfo(TokenID.If, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"if\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Implements, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"implements\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.Import, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"import\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.In, Reservation.TypeScriptAndJS, OperatorPrecedence.Relational, NodeType.In, OperatorPrecedence.None, NodeType.None, \"in\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.InstanceOf, Reservation.TypeScriptAndJS, OperatorPrecedence.Relational, NodeType.InstOf, OperatorPrecedence.None, NodeType.None, \"instanceof\", ErrorRecoverySet.BinOp);\n setTokenInfo(TokenID.Interface, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"interface\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.Let, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"let\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.Module, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"module\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.New, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"new\", ErrorRecoverySet.PreOp);\n setTokenInfo(TokenID.Number, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"number\", ErrorRecoverySet.PrimType);\n setTokenInfo(TokenID.Null, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"null\", ErrorRecoverySet.RLit);\n setTokenInfo(TokenID.Package, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"package\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.Private, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"private\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.Protected, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"protected\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.Public, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"public\", ErrorRecoverySet.TypeScriptS);\n setTokenInfo(TokenID.Return, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"return\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.Static, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"static\", ErrorRecoverySet.None);\n setTokenInfo(TokenID.String, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"string\", ErrorRecoverySet.PrimType);\n setTokenInfo(TokenID.Super, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"super\", ErrorRecoverySet.RLit);\n setTokenInfo(TokenID.Switch, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"switch\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.This, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"this\", ErrorRecoverySet.RLit);\n setTokenInfo(TokenID.Throw, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"throw\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.True, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"true\", ErrorRecoverySet.RLit);\n setTokenInfo(TokenID.Try, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"try\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.TypeOf, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Typeof, \"typeof\", ErrorRecoverySet.Prefix);\n setTokenInfo(TokenID.Var, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"var\", ErrorRecoverySet.Var);\n setTokenInfo(TokenID.Void, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Void, \"void\", ErrorRecoverySet.Prefix);\n setTokenInfo(TokenID.With, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.With, \"with\", ErrorRecoverySet.Stmt);\n setTokenInfo(TokenID.While, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"while\", ErrorRecoverySet.While);\n setTokenInfo(TokenID.Yield, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"yield\", ErrorRecoverySet.None);\n\n setTokenInfo(TokenID.Identifier, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"identifier\", ErrorRecoverySet.ID);\n setTokenInfo(TokenID.NumberLiteral, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"numberLiteral\", ErrorRecoverySet.Literal);\n setTokenInfo(TokenID.RegularExpressionLiteral, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"regex\", ErrorRecoverySet.RegExp);\n setTokenInfo(TokenID.StringLiteral, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"qstring\", ErrorRecoverySet.Literal);\n\n // Non-operator non-identifier tokens\n setTokenInfo(TokenID.Semicolon, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \";\", ErrorRecoverySet.SColon); // ;\n setTokenInfo(TokenID.CloseParen, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \")\", ErrorRecoverySet.RParen); // )\n setTokenInfo(TokenID.CloseBracket, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"]\", ErrorRecoverySet.RBrack); // ]\n setTokenInfo(TokenID.OpenBrace, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"{\", ErrorRecoverySet.LCurly); // {\n setTokenInfo(TokenID.CloseBrace, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"}\", ErrorRecoverySet.RCurly); // }\n setTokenInfo(TokenID.DotDotDot, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"...\", ErrorRecoverySet.None); // ...\n\n // Operator non-identifier tokens\n setTokenInfo(TokenID.Comma, Reservation.None, OperatorPrecedence.Comma, NodeType.Comma, OperatorPrecedence.None, NodeType.None, \",\", ErrorRecoverySet.Comma); // ,\n setTokenInfo(TokenID.Equals, Reservation.None, OperatorPrecedence.Assignment, NodeType.Asg, OperatorPrecedence.None, NodeType.None, \"=\", ErrorRecoverySet.Asg); // =\n setTokenInfo(TokenID.PlusEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgAdd, OperatorPrecedence.None, NodeType.None, \"+=\", ErrorRecoverySet.BinOp); // +=\n setTokenInfo(TokenID.MinusEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgSub, OperatorPrecedence.None, NodeType.None, \"-=\", ErrorRecoverySet.BinOp); // -=\n setTokenInfo(TokenID.AsteriskEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgMul, OperatorPrecedence.None, NodeType.None, \"*=\", ErrorRecoverySet.BinOp); // *=\n\n setTokenInfo(TokenID.SlashEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgDiv, OperatorPrecedence.None, NodeType.None, \"/=\", ErrorRecoverySet.BinOp); // /=\n setTokenInfo(TokenID.PercentEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgMod, OperatorPrecedence.None, NodeType.None, \"%=\", ErrorRecoverySet.BinOp); // %=\n setTokenInfo(TokenID.AmpersandEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgAnd, OperatorPrecedence.None, NodeType.None, \"&=\", ErrorRecoverySet.BinOp); // &=\n setTokenInfo(TokenID.CaretEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgXor, OperatorPrecedence.None, NodeType.None, \"^=\", ErrorRecoverySet.BinOp); // ^=\n setTokenInfo(TokenID.BarEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgOr, OperatorPrecedence.None, NodeType.None, \"|=\", ErrorRecoverySet.BinOp); // |=\n setTokenInfo(TokenID.LessThanLessThanEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgLsh, OperatorPrecedence.None, NodeType.None, \"<<=\", ErrorRecoverySet.BinOp); // <<=\n setTokenInfo(TokenID.GreaterThanGreaterThanEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgRsh, OperatorPrecedence.None, NodeType.None, \">>=\", ErrorRecoverySet.BinOp); // >>=\n setTokenInfo(TokenID.GreaterThanGreaterThanGreaterThanEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgRs2, OperatorPrecedence.None, NodeType.None, \">>>=\", ErrorRecoverySet.BinOp); // >>>=\n setTokenInfo(TokenID.Question, Reservation.None, OperatorPrecedence.Conditional, NodeType.ConditionalExpression, OperatorPrecedence.None, NodeType.None, \"?\", ErrorRecoverySet.BinOp); // ?\n setTokenInfo(TokenID.Colon, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \":\", ErrorRecoverySet.Colon); // :\n setTokenInfo(TokenID.BarBar, Reservation.None, OperatorPrecedence.LogicalOr, NodeType.LogOr, OperatorPrecedence.None, NodeType.None, \"||\", ErrorRecoverySet.BinOp); // ||\n setTokenInfo(TokenID.AmpersandAmpersand, Reservation.None, OperatorPrecedence.LogicalAnd, NodeType.LogAnd, OperatorPrecedence.None, NodeType.None, \"&&\", ErrorRecoverySet.BinOp); // &&\n setTokenInfo(TokenID.Bar, Reservation.None, OperatorPrecedence.BitwiseOr, NodeType.Or, OperatorPrecedence.None, NodeType.None, \"|\", ErrorRecoverySet.BinOp); // |\n setTokenInfo(TokenID.Caret, Reservation.None, OperatorPrecedence.BitwiseExclusiveOr, NodeType.Xor, OperatorPrecedence.None, NodeType.None, \"^\", ErrorRecoverySet.BinOp); // ^\n setTokenInfo(TokenID.And, Reservation.None, OperatorPrecedence.BitwiseAnd, NodeType.And, OperatorPrecedence.None, NodeType.None, \"&\", ErrorRecoverySet.BinOp); // &\n setTokenInfo(TokenID.EqualsEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.Eq, OperatorPrecedence.None, NodeType.None, \"==\", ErrorRecoverySet.BinOp); // ==\n setTokenInfo(TokenID.ExclamationEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.Ne, OperatorPrecedence.None, NodeType.None, \"!=\", ErrorRecoverySet.BinOp); // !=\n setTokenInfo(TokenID.EqualsEqualsEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.Eqv, OperatorPrecedence.None, NodeType.None, \"===\", ErrorRecoverySet.BinOp); // ===\n setTokenInfo(TokenID.ExclamationEqualsEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.NEqv, OperatorPrecedence.None, NodeType.None, \"!==\", ErrorRecoverySet.BinOp); // !==\n setTokenInfo(TokenID.LessThan, Reservation.None, OperatorPrecedence.Relational, NodeType.Lt, OperatorPrecedence.None, NodeType.None, \"<\", ErrorRecoverySet.BinOp); // <\n setTokenInfo(TokenID.LessThanEquals, Reservation.None, OperatorPrecedence.Relational, NodeType.Le, OperatorPrecedence.None, NodeType.None, \"<=\", ErrorRecoverySet.BinOp); // <=\n setTokenInfo(TokenID.GreaterThan, Reservation.None, OperatorPrecedence.Relational, NodeType.Gt, OperatorPrecedence.None, NodeType.None, \">\", ErrorRecoverySet.BinOp); // >\n setTokenInfo(TokenID.GreaterThanEquals, Reservation.None, OperatorPrecedence.Relational, NodeType.Ge, OperatorPrecedence.None, NodeType.None, \">=\", ErrorRecoverySet.BinOp); // >=\n setTokenInfo(TokenID.LessThanLessThan, Reservation.None, OperatorPrecedence.Shift, NodeType.Lsh, OperatorPrecedence.None, NodeType.None, \"<<\", ErrorRecoverySet.BinOp); // <<\n setTokenInfo(TokenID.GreaterThanGreaterThan, Reservation.None, OperatorPrecedence.Shift, NodeType.Rsh, OperatorPrecedence.None, NodeType.None, \">>\", ErrorRecoverySet.BinOp); // >>\n setTokenInfo(TokenID.GreaterThanGreaterThanGreaterThan, Reservation.None, OperatorPrecedence.Shift, NodeType.Rs2, OperatorPrecedence.None, NodeType.None, \">>>\", ErrorRecoverySet.BinOp); // >>>\n setTokenInfo(TokenID.Plus, Reservation.None, OperatorPrecedence.Additive, NodeType.Add, OperatorPrecedence.Unary, NodeType.Pos, \"+\", ErrorRecoverySet.AddOp); // +\n setTokenInfo(TokenID.Minus, Reservation.None, OperatorPrecedence.Additive, NodeType.Sub, OperatorPrecedence.Unary, NodeType.Neg, \"-\", ErrorRecoverySet.AddOp); // -\n setTokenInfo(TokenID.Asterisk, Reservation.None, OperatorPrecedence.Multiplicative, NodeType.Mul, OperatorPrecedence.None, NodeType.None, \"*\", ErrorRecoverySet.BinOp); // *\n setTokenInfo(TokenID.Slash, Reservation.None, OperatorPrecedence.Multiplicative, NodeType.Div, OperatorPrecedence.None, NodeType.None, \"/\", ErrorRecoverySet.BinOp); // /\n setTokenInfo(TokenID.Percent, Reservation.None, OperatorPrecedence.Multiplicative, NodeType.Mod, OperatorPrecedence.None, NodeType.None, \"%\", ErrorRecoverySet.BinOp); // %\n setTokenInfo(TokenID.Tilde, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Not, \"~\", ErrorRecoverySet.PreOp); // ~\n setTokenInfo(TokenID.Exclamation, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.LogNot, \"!\", ErrorRecoverySet.PreOp); // !\n setTokenInfo(TokenID.PlusPlus, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.IncPre, \"++\", ErrorRecoverySet.PreOp); // ++\n setTokenInfo(TokenID.MinusMinus, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.DecPre, \"--\", ErrorRecoverySet.PreOp); // --\n setTokenInfo(TokenID.OpenParen, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"(\", ErrorRecoverySet.LParen); // (\n setTokenInfo(TokenID.OpenBracket, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"[\", ErrorRecoverySet.LBrack); // [\n setTokenInfo(TokenID.Dot, Reservation.None, OperatorPrecedence.Unary, NodeType.None, OperatorPrecedence.None, NodeType.None, \".\", ErrorRecoverySet.Dot); // .\n setTokenInfo(TokenID.EndOfFile, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"<EOF>\", ErrorRecoverySet.EOF); // EOF\n setTokenInfo(TokenID.EqualsGreaterThan, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"=>\", ErrorRecoverySet.None); // =>\n\n export function lookupToken(tokenId: TokenID): TokenInfo {\n return tokenTable[tokenId];\n }\n\n export enum TokenClass {\n Punctuation,\n Keyword,\n Operator,\n Comment,\n Whitespace,\n Identifier,\n NumberLiteral,\n StringLiteral,\n RegExpLiteral,\n }\n\n export class SavedToken {\n constructor (public tok: Token, public minChar: number, public limChar: number) { }\n }\n\n export class Token {\n constructor (public tokenId: TokenID) {\n }\n\n public toString() {\n return \"token: \" + this.tokenId + \" \" + this.getText() + \" (\" + (<any>TokenID)._map[this.tokenId] + \")\";\n }\n\n public print(line: number, outfile) {\n outfile.WriteLine(this.toString() + \",on line\" + line);\n }\n\n public getText(): string {\n return tokenTable[this.tokenId].text;\n }\n\n public classification(): TokenClass {\n if (this.tokenId <= TokenID.LimKeyword) {\n return TokenClass.Keyword;\n }\n else {\n var tokenInfo = lookupToken(this.tokenId);\n if (tokenInfo != undefined) {\n if ((tokenInfo.unopNodeType != NodeType.None) ||\n (tokenInfo.binopNodeType != NodeType.None)) {\n return TokenClass.Operator;\n }\n }\n }\n\n return TokenClass.Punctuation;\n }\n }\n\n export class NumberLiteralToken extends Token {\n constructor (public value: number, public hasEmptyFraction?: bool) {\n super(TokenID.NumberLiteral);\n }\n\n public getText(): string {\n return this.hasEmptyFraction ? this.value.toString() + \".0\" : this.value.toString();\n }\n\n public classification(): TokenClass {\n return TokenClass.NumberLiteral;\n }\n }\n\n export class StringLiteralToken extends Token {\n constructor (public value: string) {\n super(TokenID.StringLiteral);\n }\n\n public getText(): string {\n return this.value;\n }\n\n public classification(): TokenClass {\n return TokenClass.StringLiteral;\n }\n }\n\n export class IdentifierToken extends Token {\n constructor (public value: string, public hasEscapeSequence : bool) {\n super(TokenID.Identifier);\n }\n public getText(): string {\n return this.value;\n }\n public classification(): TokenClass {\n return TokenClass.Identifier;\n }\n }\n\n export class WhitespaceToken extends Token {\n constructor (tokenId: TokenID, public value: string) {\n super(tokenId);\n }\n\n public getText(): string {\n return this.value;\n }\n\n public classification(): TokenClass {\n return TokenClass.Whitespace;\n }\n }\n\n export class CommentToken extends Token {\n constructor (tokenID: TokenID, public value: string, public isBlock: bool, public startPos: number, public line: number, public endsLine: bool) {\n super(tokenID);\n }\n\n public getText(): string {\n return this.value;\n }\n\n public classification(): TokenClass {\n return TokenClass.Comment;\n }\n }\n\n export class RegularExpressionLiteralToken extends Token {\n constructor(public regex) {\n super(TokenID.RegularExpressionLiteral);\n }\n\n public getText(): string {\n return this.regex.toString();\n }\n\n public classification(): TokenClass {\n return TokenClass.RegExpLiteral;\n }\n }\n\n // TODO: new with length TokenID.LimFixed\n export var staticTokens = new Token[];\n export function initializeStaticTokens() {\n for (var i = 0; i <= TokenID.LimFixed; i++) {\n staticTokens[i] = new Token(i);\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///<reference path='typescript.ts'/>\n///<reference path='io.ts'/>\n///<reference path='optionsParser.ts'/>\n\nclass CommandLineHost implements TypeScript.IResolverHost {\n\n public pathMap: any = {};\n public resolvedPaths: any = {};\n\n constructor(public compilationSettings: TypeScript.CompilationSettings) { \n }\n\n public getPathIdentifier(path: string) { \n return this.compilationSettings.useCaseSensitiveFileResolution ? path : path.toLocaleUpperCase();\n }\n\n public isResolved(path: string) {\n return this.resolvedPaths[this.getPathIdentifier(this.pathMap[path])] != undefined;\n }\n\n public resolveCompilationEnvironment(preEnv: TypeScript.CompilationEnvironment,\n resolver: TypeScript.ICodeResolver,\n traceDependencies: bool): TypeScript.CompilationEnvironment {\n var resolvedEnv = new TypeScript.CompilationEnvironment(preEnv.compilationSettings, preEnv.ioHost);\n\n var nCode = preEnv.code.length;\n var path = \"\";\n\n var postResolutionError = \n (errorFile: string, errorMessage: string) => {\n TypeScript.CompilerDiagnostics.debugPrint(\"Could not resolve file '\" + errorFile + \"'\" + (errorMessage == \"\" ? \"\" : \": \" + errorMessage));\n }\n\n var resolutionDispatcher: TypeScript.IResolutionDispatcher = {\n postResolutionError: postResolutionError,\n postResolution: (path: string, code: TypeScript.ISourceText) => {\n var pathId = this.getPathIdentifier(path);\n if (!this.resolvedPaths[pathId]) {\n resolvedEnv.code.push(<TypeScript.SourceUnit>code);\n this.resolvedPaths[pathId] = true;\n }\n }\n };\n\n for (var i = 0; i < nCode; i++) {\n path = TypeScript.switchToForwardSlashes(preEnv.ioHost.resolvePath(preEnv.code[i].path));\n this.pathMap[preEnv.code[i].path] = path;\n resolver.resolveCode(path, \"\", false, resolutionDispatcher);\n }\n\n return resolvedEnv;\n }\n}\nclass BatchCompiler {\n public compilationSettings: TypeScript.CompilationSettings;\n public compilationEnvironment: TypeScript.CompilationEnvironment;\n public resolvedEnvironment: TypeScript.CompilationEnvironment = null;\n public hasResolveErrors: bool = false;\n public compilerVersion = \"0.8.2.0\";\n public printedVersion = false;\n\n constructor (public ioHost: IIO) { \n this.compilationSettings = new TypeScript.CompilationSettings();\n this.compilationEnvironment = new TypeScript.CompilationEnvironment(this.compilationSettings, this.ioHost);\n }\n\n public resolve() {\n var resolver = new TypeScript.CodeResolver(this.compilationEnvironment);\n var commandLineHost = new CommandLineHost(this.compilationSettings);\n var ret = commandLineHost.resolveCompilationEnvironment(this.compilationEnvironment, resolver, true);\n\n // Reset resolve error status\n this.hasResolveErrors = false;\n\n for (var i = 0; i < this.compilationEnvironment.code.length; i++) {\n if (!commandLineHost.isResolved(this.compilationEnvironment.code[i].path)) {\n this.hasResolveErrors = true;\n var path = this.compilationEnvironment.code[i].path;\n if (!TypeScript.isSTRFile(path) && !TypeScript.isDSTRFile(path) && !TypeScript.isTSFile(path) && !TypeScript.isDTSFile(path)) {\n this.ioHost.stderr.WriteLine(\"Unknown extension for file: \\\"\"+path+\"\\\". Only .ts and .d.ts extensions are allowed.\");\n }\n else {\n this.ioHost.stderr.WriteLine(\"Error reading file \\\"\" + path + \"\\\": File not found\");\n }\n }\n }\n\n return ret;\n }\n \n /// Do the actual compilation reading from input files and\n /// writing to output file(s).\n public compile(): bool {\n var compiler: TypeScript.TypeScriptCompiler;\n\n compiler = new TypeScript.TypeScriptCompiler(this.ioHost.stderr, new TypeScript.NullLogger(), this.compilationSettings);\n compiler.setErrorOutput(this.ioHost.stderr);\n compiler.setErrorCallback(\n (minChar, charLen, message, unitIndex) => {\n compiler.errorReporter.hasErrors = true;\n var fname = this.resolvedEnvironment.code[unitIndex].path;\n var lineCol = { line: -1, col: -1 };\n compiler.parser.getSourceLineCol(lineCol, minChar);\n // line is 1-base, col, however, is 0-base. add 1 to the col before printing the message\n var msg = fname + \" (\" + lineCol.line + \",\" + (lineCol.col + 1) + \"): \" + message;\n if (this.compilationSettings.errorRecovery) {\n this.ioHost.stderr.WriteLine(msg);\n } else {\n throw new SyntaxError(msg);\n }\n });\n\n if (this.compilationSettings.emitComments) {\n compiler.emitCommentsToOutput();\n }\n\n var consumeUnit = (code: TypeScript.SourceUnit, addAsResident: bool) => {\n try {\n // if file resolving is disabled, the file's content will not yet be loaded\n\n if (!this.compilationSettings.resolve) {\n code.content = this.ioHost.readFile(code.path);\n // If declaration files are going to be emitted, \n // preprocess the file contents and add in referenced files as well\n if (this.compilationSettings.generateDeclarationFiles) {\n TypeScript.CompilerDiagnostics.assert(code.referencedFiles == null, \"With no resolve option, referenced files need to null\");\n code.referencedFiles = TypeScript.getReferencedFiles(code);\n }\n }\n\n if (code.content != null) {\n if (this.compilationSettings.parseOnly) {\n compiler.parseUnit(code.content, code.path);\n }\n else {\n if (this.compilationSettings.errorRecovery) {\n compiler.parser.setErrorRecovery(this.ioHost.stderr);\n }\n compiler.addUnit(code.content, code.path, addAsResident, code.referencedFiles);\n }\n }\n }\n catch (err) {\n compiler.errorReporter.hasErrors = true;\n // This includes syntax errors thrown from error callback if not in recovery mode\n this.ioHost.stderr.WriteLine(err.message);\n }\n\n }\n\n for (var iCode = 0 ; iCode < this.resolvedEnvironment.code.length; iCode++) {\n if (!this.compilationSettings.parseOnly || (iCode > 0)) {\n consumeUnit(this.resolvedEnvironment.code[iCode], false);\n }\n }\n\n var emitterIOHost = {\n createFile: (fileName: string, useUTF8?: bool) => IOUtils.createFileAndFolderStructure(this.ioHost, fileName, useUTF8),\n directoryExists: this.ioHost.directoryExists,\n fileExists: this.ioHost.fileExists,\n resolvePath: this.ioHost.resolvePath\n };\n\n try {\n if (!this.compilationSettings.parseOnly) {\n compiler.typeCheck();\n compiler.emit(emitterIOHost);\n compiler.emitDeclarations();\n }\n else {\n compiler.emitAST(emitterIOHost);\n }\n } catch (err) {\n compiler.errorReporter.hasErrors = true;\n // Catch emitter exceptions\n if (err.message != \"EmitError\") {\n throw err;\n }\n }\n\n return compiler.errorReporter.hasErrors;\n }\n\n // Execute the provided inputs\n public run() {\n for (var i = 0; i < this.compilationEnvironment.code.length; i++) {\n var unit = this.compilationEnvironment.code[i];\n \n var outputFileName: string = unit.path;\n if (TypeScript.isTSFile(outputFileName)) {\n outputFileName = outputFileName.replace(/\\.ts$/, \".js\");\n } else if (TypeScript.isSTRFile(outputFileName)) {\n outputFileName = outputFileName.replace(/\\.str$/, \".js\");\n }\n if (this.ioHost.fileExists(outputFileName)) {\n var unitRes = this.ioHost.readFile(outputFileName)\n this.ioHost.run(unitRes, outputFileName);\n }\n }\n }\n\n /// Begin batch compilation\n public batchCompile() {\n TypeScript.CompilerDiagnostics.diagnosticWriter = { Alert: (s: string) => { this.ioHost.printLine(s); } }\n\n var code: TypeScript.SourceUnit;\n\n var opts = new OptionsParser(this.ioHost);\n\n opts.option('out', {\n usage: 'Concatenate and emit output to single file | Redirect output structure to the directory',\n type: 'file|directory',\n set: (str) => {\n this.compilationSettings.outputOption = str;\n }\n });\n\n opts.option('style', {\n usage: 'Select style checking options (examples --style requireSemi:off or --style \"eqeqeq;bitwise:off\")',\n experimental: true,\n set: (str) => {\n this.compilationSettings.setStyleOptions(str);\n }\n });\n\n opts.flag('sourcemap', {\n usage: 'Generates corresponding .map file',\n set: () => {\n this.compilationSettings.mapSourceFiles = true;\n }\n });\n\n opts.flag('declaration', {\n usage: 'Generates corresponding .d.ts file',\n set: () => {\n this.compilationSettings.generateDeclarationFiles = true;\n }\n });\n\n if (this.ioHost.watchFile) {\n opts.flag('watch', {\n usage: 'Watch output files',\n set: () => {\n this.compilationSettings.watch = true;\n }\n }, 'w');\n }\n\n opts.flag('exec', {\n usage: 'Execute the script after compilation',\n set: () => {\n this.compilationSettings.exec = true;\n }\n }, 'e');\n\n opts.flag('parse', {\n usage: 'Parse only',\n experimental: true,\n set: () => {\n this.compilationSettings.parseOnly = true;\n }\n });\n\n opts.flag('minw', {\n usage: 'Minimize whitespace',\n experimental: true,\n set: () => { this.compilationSettings.minWhitespace = true; }\n }, 'mw');\n\n opts.flag('const', {\n usage: 'Propagate constants to emitted code',\n experimental: true,\n set: () => { this.compilationSettings.propagateConstants = true; }\n });\n\n opts.flag('errorrecovery', {\n usage: 'Enable error recovery',\n experimental: true,\n set: () => {\n this.compilationSettings.errorRecovery = true;\n }\n }, 'er');\n\n opts.flag('comments', {\n usage: 'Emit comments to output',\n set: () => {\n this.compilationSettings.emitComments = true;\n }\n }, 'c');\n\n opts.flag('cflow', {\n usage: 'Control flow',\n experimental: true,\n set: () => {\n this.compilationSettings.controlFlow = true;\n }\n });\n\n opts.flag('cflowp', {\n usage: 'Print control flow',\n experimental: true,\n set: () => {\n this.compilationSettings.controlFlow = true;\n this.compilationSettings.printControlFlow = true;\n }\n });\n\n opts.flag('cflowu', {\n usage: 'Print Use Def control flow',\n experimental: true,\n set: () => {\n this.compilationSettings.controlFlow = true;\n this.compilationSettings.controlFlowUseDef = true;\n }\n });\n\n opts.flag('noerroronwith', {\n usage: 'Allow with statements',\n experimental: true,\n set: () => {\n this.compilationSettings.errorOnWith = false;\n }\n });\n\n opts.flag('noresolve', {\n usage: 'Skip resolution and preprocessing',\n experimental: true,\n set: () => {\n this.compilationSettings.resolve = false;\n this.compilationSettings.preprocess = false;\n }\n });\n\n opts.flag('debug', {\n usage: 'Print debug output',\n experimental: true,\n set: () => {\n TypeScript.CompilerDiagnostics.debug = true;\n }\n });\n\n opts.flag('canCallDefinitionSignature', {\n usage: 'Allows you to call the definition signature of an overload group',\n experimental: true,\n set: () => {\n this.compilationSettings.canCallDefinitionSignature = true;\n }\n });\n\n opts.flag('nooptimizemodules', {\n usage: 'Do not optimize module codegen',\n experimental: true,\n set: () => {\n TypeScript.optimizeModuleCodeGen = false;\n }\n });\n\n opts.flag('nolib', {\n usage: 'Do not include a default lib.d.ts with global declarations',\n set: () => {\n this.compilationSettings.useDefaultLib = false;\n }\n });\n\n\n opts.flag('inferProperties', {\n usage: 'Infer class properties from top-level assignments to \\'this\\'',\n experimental: true,\n set: () => {\n this.compilationSettings.inferPropertiesFromThisAssignment = true;\n }\n });\n\n opts.option('target', {\n usage: 'Specify ECMAScript target version: \"ES3\" (default), or \"ES5\"',\n type: 'VER',\n set: (type) => {\n type = type.toLowerCase();\n\n if (type === 'es3') {\n this.compilationSettings.codeGenTarget = TypeScript.CodeGenTarget.ES3;\n } else if (type === 'es5') {\n this.compilationSettings.codeGenTarget = TypeScript.CodeGenTarget.ES5;\n }\n else {\n this.ioHost.printLine(\"ECMAScript target version '\" + type + \"' not supported. Using default 'ES3' code generation\");\n }\n }\n });\n\n opts.option('module', {\n usage: 'Specify module code generation: \"commonjs\" (default) or \"amd\"',\n type: 'kind',\n set: (type) => {\n type = type.toLowerCase();\n\n if (type === 'commonjs' || type === 'node') {\n TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Synchronous;\n } else if (type === 'amd') {\n TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Asynchronous;\n } else {\n this.ioHost.printLine(\"Module code generation '\" + type + \"' not supported. Using default 'commonjs' code generation\");\n }\n }\n });\n\n var printedUsage = false;\n\n opts.flag('help', {\n usage: 'Print this message',\n set: () => {\n this.printVersion();\n opts.printUsage();\n printedUsage = true;\n }\n }, 'h');\n\n opts.flag('useCaseSensitiveFileResolution', {\n usage: 'Force file resolution to be case sensitive',\n experimental: true,\n set: () => {\n this.compilationSettings.useCaseSensitiveFileResolution = true;\n }\n });\n\n opts.flag('version', {\n usage: 'Print the compiler\\'s version: ' + this.compilerVersion,\n set: () => {\n this.printVersion();\n }\n }, 'v');\n\n opts.parse(this.ioHost.arguments);\n \n if (this.compilationSettings.useDefaultLib) {\n var compilerFilePath = this.ioHost.getExecutingFilePath()\n var binDirPath = this.ioHost.dirName(compilerFilePath);\n var libStrPath = this.ioHost.resolvePath(binDirPath + \"/lib.d.ts\");\n code = new TypeScript.SourceUnit(libStrPath, null);\n this.compilationEnvironment.code.push(code);\n }\n\n for (var i = 0; i < opts.unnamed.length; i++) {\n code = new TypeScript.SourceUnit(opts.unnamed[i], null);\n this.compilationEnvironment.code.push(code);\n }\n\n // If no source files provided to compiler - print usage information\n if (this.compilationEnvironment.code.length == (this.compilationSettings.useDefaultLib ? 1 : 0)) {\n if (!printedUsage && !this.printedVersion) {\n this.printVersion();\n opts.printUsage();\n this.ioHost.quit(1);\n }\n return;\n }\n\n var sourceFiles: TypeScript.SourceUnit[] = [];\n if (this.compilationSettings.watch) {\n // Capture the state before calling resolve\n sourceFiles = this.compilationEnvironment.code.slice(0);\n }\n\n // Resolve file dependencies, if requested\n this.resolvedEnvironment = this.compilationSettings.resolve ? this.resolve() : this.compilationEnvironment;\n\n var hasCompileErrors = this.compile();\n\n var hasErrors = hasCompileErrors || this.hasResolveErrors;\n if (!hasErrors) {\n if (this.compilationSettings.exec) {\n this.run();\n }\n }\n\n if (this.compilationSettings.watch) {\n // Watch will cause the program to stick around as long as the files exist\n this.watchFiles(sourceFiles);\n }\n else { \n // Exit with the appropriate error code\n this.ioHost.quit(hasErrors ? 1 : 0);\n }\n }\n\n public printVersion() {\n if (!this.printedVersion) {\n this.ioHost.printLine(\"Version \" + this.compilerVersion);\n this.printedVersion = true;\n }\n }\n\n public watchFiles(soruceFiles: TypeScript.SourceUnit[]) {\n if (!this.ioHost.watchFile) {\n this.ioHost.printLine(\"Error: Current host does not support -w[atch] option\");\n return;\n }\n\n var resolvedFiles: string[] = []\n var watchers: { [x: string]: IFileWatcher; } = {};\n\n var addWatcher = (filename: string) => {\n if (!watchers[filename]) {\n var watcher = this.ioHost.watchFile(filename, onWatchedFileChange);\n watchers[filename] = watcher;\n }\n else {\n throw new Error(\"Cannot watch file, it is already watched.\");\n }\n };\n\n var removeWatcher = (filename: string) => {\n if (watchers[filename]) {\n watchers[filename].close();\n delete watchers[filename];\n }\n else {\n throw new Error(\"Cannot stop watching file, it is not being watched.\");\n }\n };\n\n var onWatchedFileChange = () => {\n // Reset the state\n this.compilationEnvironment.code = soruceFiles;\n\n // Resolve file dependencies, if requested\n this.resolvedEnvironment = this.compilationSettings.resolve ? this.resolve() : this.compilationEnvironment;\n\n // Check if any new files were added to the environment as a result of the file change\n var oldFiles = resolvedFiles;\n var newFiles: string[] = [];\n this.resolvedEnvironment.code.forEach((sf) => newFiles.push(sf.path));\n newFiles = newFiles.sort();\n\n var i = 0, j = 0;\n while (i < oldFiles.length && j < newFiles.length) {\n\n var compareResult = oldFiles[i].localeCompare(newFiles[j]);\n if (compareResult == 0) {\n // No change here\n i++;\n j++;\n }\n else if (compareResult < 0) {\n // Entry in old list does not exist in the new one, it was removed\n removeWatcher(oldFiles[i]);\n i++;\n }\n else {\n // Entry in new list does exist in the new one, it was added\n addWatcher(newFiles[j]);\n j++;\n }\n }\n\n // All remaining unmatched items in the old list have been removed\n for (var k = i; k < oldFiles.length; k++) {\n removeWatcher(oldFiles[k]);\n }\n\n // All remaing unmatched items in the new list have been added\n for (var k = j; k < newFiles.length; k++) {\n addWatcher(newFiles[k]);\n }\n\n // Update the state\n resolvedFiles = newFiles;;\n\n // Print header\n this.ioHost.printLine(\"\");\n this.ioHost.printLine(\"Recompiling (\" + new Date() + \"): \");\n resolvedFiles.forEach((f) => this.ioHost.printLine(\" \" + f));\n\n // Trigger a new compilation\n var hasCompileErrors = this.compile();\n\n var hasErrors = hasCompileErrors || this.hasResolveErrors;\n if (!hasErrors) {\n if (this.compilationSettings.exec) {\n this.run();\n }\n }\n };\n\n // Switch to using stdout for all error messages\n this.ioHost.stderr = this.ioHost.stdout;\n\n // Initialize the initial list of resolved files, and add watches to them\n this.resolvedEnvironment.code.forEach((sf) => {\n resolvedFiles.push(sf.path);\n addWatcher(sf.path);\n });\n resolvedFiles.sort();\n }\n}\n\n// Start the batch compilation using the current hosts IO\nvar batch = new BatchCompiler(IO);\nbatch.batchCompile();\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class ArrayCache {\n public arrayType: Type;\n public arrayBase: Type = null;\n\n public specialize(arrInstType: Type, checker: TypeChecker): Type {\n if (this.arrayBase == null) {\n this.arrayBase = arrInstType.specializeType(checker.wildElm.type, this.arrayType.elementType,\n checker, true);\n }\n return this.arrayBase;\n }\n }\n\n export class TypeComparisonInfo {\n public onlyCaptureFirstError = false;\n public flags: TypeRelationshipFlags = TypeRelationshipFlags.SuccessfulComparison;\n public message = \"\";\n\n public addMessageToFront(message) {\n if (!this.onlyCaptureFirstError) {\n this.message = this.message ? message + \":\\n\\t\" + this.message : message;\n }\n else {\n this.setMessage(message);\n }\n }\n\n public setMessage(message) {\n this.message = message;\n }\n }\n\n export interface SignatureData {\n parameters: ParameterSymbol[];\n nonOptionalParameterCount: number;\n }\n\n export interface ApplicableSignature {\n signature: Signature;\n hadProvisionalErrors: bool;\n }\n\n export enum TypeCheckCollectionMode {\n Resident,\n Transient\n }\n\n export class PersistentGlobalTypeState {\n public importedGlobalsTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n public importedGlobalsTypeTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n public importedGlobals: SymbolScopeBuilder;\n\n // transient state\n public globals: IHashTable = null;\n public globalTypes: IHashTable = null;\n public ambientGlobals: IHashTable = null;\n public ambientGlobalTypes: IHashTable = null;\n\n // resident state\n public residentGlobalValues = new StringHashTable();\n public residentGlobalTypes = new StringHashTable();\n public residentGlobalAmbientValues = new StringHashTable();\n public residentGlobalAmbientTypes = new StringHashTable();\n\n // dual resident/transient state\n\n // REVIEW: We shouldn't need to allocate private hash tables for these, since there's no private global scope\n // REVIEW: In general, we should audit each instance of DualStringHashTable to ensure that both the primary\n // and secondary tables are necessary. If it's not necessary, we should sub in a constant sentinel value.\n public dualGlobalValues: DualStringHashTable;\n public dualGlobalTypes: DualStringHashTable;\n public dualAmbientGlobalValues: DualStringHashTable;\n public dualAmbientGlobalTypes: DualStringHashTable;\n\n public globalScope: SymbolScope;\n\n public voidType: Type;\n public booleanType: Type;\n public doubleType: Type;\n\n public stringType: Type;\n public anyType: Type;\n public nullType: Type;\n public undefinedType: Type;\n\n // Use this flag to turn resident checking on and off\n public residentTypeCheck: bool = true;\n\n public mod: ModuleType = null;\n public gloMod: TypeSymbol = null;\n\n public wildElm: TypeSymbol = null;\n\n constructor (public errorReporter: ErrorReporter) {\n this.importedGlobals = new SymbolScopeBuilder(null, this.importedGlobalsTable, null, this.importedGlobalsTypeTable, null, null);\n\n this.dualGlobalValues = new DualStringHashTable(this.residentGlobalValues, new StringHashTable());\n this.dualGlobalTypes = new DualStringHashTable(this.residentGlobalTypes, new StringHashTable());\n this.dualAmbientGlobalValues = new DualStringHashTable(this.residentGlobalAmbientValues, new StringHashTable());\n this.dualAmbientGlobalTypes = new DualStringHashTable(this.residentGlobalAmbientTypes, new StringHashTable());\n\n var dualGlobalScopedMembers = new ScopedMembers(new DualStringHashTable(this.dualGlobalValues, new StringHashTable()));\n var dualGlobalScopedAmbientMembers = new ScopedMembers(new DualStringHashTable(this.dualAmbientGlobalValues, new StringHashTable()));\n var dualGlobalScopedEnclosedTypes = new ScopedMembers(new DualStringHashTable(this.dualGlobalTypes, new StringHashTable()));\n var dualGlobalScopedAmbientEnclosedTypes = new ScopedMembers(new DualStringHashTable(this.dualAmbientGlobalTypes, new StringHashTable()));\n\n this.globalScope = new SymbolScopeBuilder(dualGlobalScopedMembers, dualGlobalScopedAmbientMembers, dualGlobalScopedEnclosedTypes, dualGlobalScopedAmbientEnclosedTypes, this.importedGlobals, null);\n\n this.voidType = this.enterPrimitive(Primitive.Void, \"void\");\n this.booleanType = this.enterPrimitive(Primitive.Boolean, \"bool\");\n this.doubleType = this.enterPrimitive(Primitive.Double, \"number\");\n this.importedGlobals.ambientEnclosedTypes.addPublicMember(\"number\", this.doubleType.symbol);\n\n this.stringType = this.enterPrimitive(Primitive.String, \"string\");\n this.anyType = this.enterPrimitive(Primitive.Any, \"any\");\n this.nullType = this.enterPrimitive(Primitive.Null, \"null\");\n this.undefinedType = this.enterPrimitive(Primitive.Undefined, \"undefined\");\n\n // shared global state is resident\n this.setCollectionMode(TypeCheckCollectionMode.Resident);\n\n this.wildElm = new TypeSymbol(\"_element\", -1, 0, -1, new Type());\n this.importedGlobalsTypeTable.addPublicMember(this.wildElm.name, this.wildElm);\n\n this.mod = new ModuleType(dualGlobalScopedEnclosedTypes, dualGlobalScopedAmbientEnclosedTypes);\n this.mod.members = dualGlobalScopedMembers;\n this.mod.ambientMembers = dualGlobalScopedAmbientMembers;\n this.mod.containedScope = this.globalScope;\n\n this.gloMod = new TypeSymbol(globalId, -1, 0, -1, this.mod);\n this.mod.members.addPublicMember(this.gloMod.name, this.gloMod);\n\n this.defineGlobalValue(\"undefined\", this.undefinedType);\n }\n\n\n public enterPrimitive(flags: number, name: string) {\n var primitive = new Type();\n primitive.primitiveTypeClass = flags;\n var symbol = new TypeSymbol(name, -1, name.length, -1, primitive);\n symbol.typeCheckStatus = TypeCheckStatus.Finished;\n primitive.symbol = symbol;\n this.importedGlobals.enter(null, null, symbol, this.errorReporter, true, true, true);\n return primitive;\n }\n\n public setCollectionMode(mode: TypeCheckCollectionMode) {\n this.residentTypeCheck =\n this.dualGlobalValues.insertPrimary =\n this.dualGlobalTypes.insertPrimary =\n this.dualAmbientGlobalValues.insertPrimary =\n this.dualAmbientGlobalTypes.insertPrimary = mode == TypeCheckCollectionMode.Resident;\n }\n\n public refreshPersistentState() {\n this.globals = new StringHashTable();\n this.globalTypes = new StringHashTable();\n this.ambientGlobals = new StringHashTable();\n this.ambientGlobalTypes = new StringHashTable();\n\n // add global types to the global scope\n this.globalTypes.add(this.voidType.symbol.name, this.voidType.symbol);\n this.globalTypes.add(this.booleanType.symbol.name, this.booleanType.symbol);\n this.globalTypes.add(this.doubleType.symbol.name, this.doubleType.symbol);\n this.globalTypes.add(\"number\", this.doubleType.symbol);\n this.globalTypes.add(this.stringType.symbol.name, this.stringType.symbol);\n this.globalTypes.add(this.anyType.symbol.name, this.anyType.symbol);\n this.globalTypes.add(this.nullType.symbol.name, this.nullType.symbol);\n this.globalTypes.add(this.undefinedType.symbol.name, this.undefinedType.symbol);\n\n this.dualGlobalValues.secondaryTable = this.globals;\n this.dualGlobalTypes.secondaryTable = this.globalTypes;\n this.dualAmbientGlobalValues.secondaryTable = this.ambientGlobals;\n this.dualAmbientGlobalTypes.secondaryTable = this.ambientGlobalTypes;\n }\n\n public defineGlobalValue(name: string, type: Type) {\n var valueLocation = new ValueLocation();\n valueLocation.typeLink = new TypeLink();\n var sym = new VariableSymbol(name, 0, -1, valueLocation);\n sym.setType(type);\n sym.typeCheckStatus = TypeCheckStatus.Finished;\n sym.container = this.gloMod;\n this.importedGlobalsTable.addPublicMember(name, sym);\n }\n }\n\n export class ContextualTypeContext {\n public targetSig: Signature = null;\n public targetThis: Type = null;\n public targetAccessorType: Type = null;\n\n constructor (public contextualType: Type,\n public provisional: bool, public contextID: number) { }\n }\n\n export class ContextualTypingContextStack {\n private contextStack: ContextualTypeContext[] = [];\n static contextID = TypeCheckStatus.Finished + 1;\n public pushContextualType(type: Type, provisional: bool) { this.contextStack.push(new ContextualTypeContext(type, provisional, ContextualTypingContextStack.contextID++)); this.checker.errorReporter.pushToErrorSink = provisional; }\n public hadProvisionalErrors = false; // somewhere in the chain a provisional typecheck error was thrown\n public popContextualType() {\n var tc = this.contextStack.pop();\n this.checker.errorReporter.pushToErrorSink = this.isProvisional();\n this.hadProvisionalErrors = this.hadProvisionalErrors || (tc.provisional && (this.checker.errorReporter.getCapturedErrors().length));\n this.checker.errorReporter.freeCapturedErrors();\n return tc;\n }\n public getContextualType(): ContextualTypeContext { return (!this.contextStack.length ? null : this.contextStack[this.contextStack.length - 1]); }\n public getContextID() { return (!this.contextStack.length ? TypeCheckStatus.Finished : this.contextStack[this.contextStack.length - 1].contextID); }\n public isProvisional() { return (!this.contextStack.length ? false : this.contextStack[this.contextStack.length - 1].provisional); }\n\n constructor (public checker: TypeChecker) { }\n }\n\n export class TypeChecker {\n public errorReporter: ErrorReporter = null;\n public globalScope: SymbolScope;\n\n public checkControlFlow = false;\n public printControlFlowGraph = false;\n public checkControlFlowUseDef = false;\n public styleSettings: StyleSettings = null;\n\n public units: LocationInfo[] = null;\n\n public voidType: Type;\n public booleanType: Type;\n public numberType: Type;\n public stringType: Type;\n public anyType: Type;\n public nullType: Type;\n public undefinedType: Type;\n\n public anon = \"_anonymous\";\n\n public globals: DualStringHashTable;\n public globalTypes: DualStringHashTable;\n public ambientGlobals: DualStringHashTable;\n public ambientGlobalTypes: DualStringHashTable;\n public gloModType: ModuleType;\n public gloMod: TypeSymbol;\n public wildElm: TypeSymbol;\n\n public locationInfo: LocationInfo = null;\n public typeFlow: TypeFlow = null;\n\n public currentCompareA: Symbol = null;\n public currentCompareB: Symbol = null;\n\n public currentModDecl: ModuleDeclaration = null;\n\n public inBind = false;\n public inWith = false;\n public errorsOnWith = true;\n\n public typingContextStack: ContextualTypingContextStack;\n public currentContextualTypeContext: ContextualTypeContext = null;\n\n public resolvingBases = false;\n\n public canCallDefinitionSignature = false;\n\n public assignableCache: any[] = <any>{};\n public subtypeCache: any[] = <any>{};\n public identicalCache: any[] = <any>{};\n\n public provisionalStartedTypecheckObjects: PhasedTypecheckObject[] = [];\n\n public mustCaptureGlobalThis = false;\n\n constructor (public persistentState: PersistentGlobalTypeState) {\n this.voidType = this.persistentState.voidType;\n this.booleanType = this.persistentState.booleanType;\n this.numberType = this.persistentState.doubleType;\n this.stringType = this.persistentState.stringType;\n this.anyType = this.persistentState.anyType;\n this.nullType = this.persistentState.nullType;\n this.undefinedType = this.persistentState.undefinedType;\n\n this.globals = this.persistentState.dualGlobalValues;\n this.globalTypes = this.persistentState.dualGlobalTypes;\n this.ambientGlobals = this.persistentState.dualAmbientGlobalValues;\n this.ambientGlobalTypes = this.persistentState.dualAmbientGlobalTypes;\n this.gloModType = this.persistentState.mod;\n this.gloMod = this.persistentState.gloMod;\n this.wildElm = this.persistentState.wildElm;\n\n this.globalScope = this.persistentState.globalScope;\n\n this.typingContextStack = new ContextualTypingContextStack(this);\n }\n\n public setStyleOptions(style: StyleSettings) {\n this.styleSettings = style;\n }\n\n // Contextual typing\n public setContextualType(type: Type, provisional: bool) {\n this.typingContextStack.pushContextualType(type, provisional);\n this.currentContextualTypeContext = this.typingContextStack.getContextualType();\n }\n\n public unsetContextualType() {\n var lastTC = this.typingContextStack.popContextualType();\n this.currentContextualTypeContext = this.typingContextStack.getContextualType();\n return lastTC;\n }\n\n public hadProvisionalErrors() {\n return this.typingContextStack.hadProvisionalErrors;\n }\n public resetProvisionalErrors() {\n if (!this.typingContextStack.getContextualType()) {\n this.typingContextStack.hadProvisionalErrors = false;\n }\n }\n\n public typeCheckWithContextualType(contextType: Type, provisional: bool, condition: bool, ast: AST) {\n if (condition) {\n this.setContextualType(contextType, this.typingContextStack.isProvisional() || provisional);\n }\n this.typeFlow.typeCheck(ast);\n if (condition) {\n this.unsetContextualType();\n }\n }\n\n public resetTargetType() {\n this.currentContextualTypeContext = this.typingContextStack.getContextualType();\n }\n\n // Unset the current contextual type without disturbing the stack, effectively \"killing\" the contextual typing process\n public killCurrentContextualType() { this.currentContextualTypeContext = null; this.errorReporter.pushToErrorSink = false; }\n public hasTargetType() { return this.currentContextualTypeContext && this.currentContextualTypeContext.contextualType; }\n public getTargetTypeContext() { return this.currentContextualTypeContext; }\n\n public inProvisionalTypecheckMode() {\n return this.typingContextStack.isProvisional();\n }\n\n public getTypeCheckFinishedStatus() {\n if (this.inProvisionalTypecheckMode()) {\n return this.typingContextStack.getContextID();\n }\n return TypeCheckStatus.Finished;\n }\n\n public typeStatusIsFinished(status: TypeCheckStatus) {\n\n return status == TypeCheckStatus.Finished ||\n (this.inProvisionalTypecheckMode() && status == this.typingContextStack.getContextID());\n }\n\n public addStartedPTO(pto: PhasedTypecheckObject) {\n if (this.inProvisionalTypecheckMode()) {\n this.provisionalStartedTypecheckObjects[this.provisionalStartedTypecheckObjects.length] = pto;\n }\n }\n\n public cleanStartedPTO() {\n for (var i = 0; i < this.provisionalStartedTypecheckObjects.length; i++) {\n if (this.provisionalStartedTypecheckObjects[i].typeCheckStatus >= this.typingContextStack.getContextID()) {\n this.provisionalStartedTypecheckObjects[i].typeCheckStatus = TypeCheckStatus.NotStarted;\n }\n }\n this.provisionalStartedTypecheckObjects = [];\n }\n\n // type collection \n public collectTypes(ast: AST): void {\n if (ast.nodeType == NodeType.Script) {\n var script = <Script>ast;\n this.locationInfo = script.locationInfo;\n }\n var globalChain = new ScopeChain(this.gloMod, null, this.globalScope);\n var context = new TypeCollectionContext(globalChain, this);\n getAstWalkerFactory().walk(ast, preCollectTypes, postCollectTypes, null, context);\n }\n\n public makeArrayType(type: Type): Type {\n if (type.arrayCache == null) {\n type.arrayCache = new ArrayCache();\n type.arrayCache.arrayType = new Type();\n type.arrayCache.arrayType.elementType = type;\n type.arrayCache.arrayType.symbol = type.symbol;\n }\n return type.arrayCache.arrayType;\n }\n\n public getParameterList(funcDecl: FuncDecl, container: Symbol): SignatureData {\n var args = funcDecl.arguments;\n var parameterTable = null;\n var parameterBuilder = null;\n var len = args.members.length;\n var nonOptionalParams = 0;\n var result: ParameterSymbol[] = [];\n\n if (len > 0) {\n parameterTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n parameterBuilder = new SymbolScopeBuilder(parameterTable, null, null, null, null, container);\n\n for (var i = 0; i < len; i++) {\n var parameter = <ArgDecl>args.members[i];\n var paramDef = new ValueLocation();\n var parameterSymbol = new ParameterSymbol(parameter.id.text, parameter.minChar,\n this.locationInfo.unitIndex, paramDef);\n parameterSymbol.declAST = parameter;\n parameterSymbol.funcDecl = funcDecl;\n parameter.id.sym = parameterSymbol;\n parameter.sym = parameterSymbol;\n paramDef.symbol = parameterSymbol;\n paramDef.typeLink = getTypeLink(parameter.typeExpr, this, false);\n parameterBuilder.enter(null, parameter, parameterSymbol, this.errorReporter, true, false, false); // REVIEW: Should this be entered into the private scope?\n result[result.length] = parameterSymbol;\n if (!parameter.isOptionalArg()) {\n nonOptionalParams++;\n }\n }\n }\n return { parameters: result, nonOptionalParameterCount: nonOptionalParams };\n }\n\n // Create a signature for a function definition\n // (E.g., has a function body - function declarations, property declarations, lambdas)\n public createFunctionSignature(funcDecl: FuncDecl, container: Symbol, scope: SymbolScope, overloadGroupSym: Symbol, addToScope: bool): Signature {\n\n var isExported = hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported) || container == this.gloMod;\n var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);\n var isDefinition = hasFlag(funcDecl.fncFlags, FncFlags.Definition);\n var isAmbient = hasFlag(funcDecl.fncFlags, FncFlags.Ambient);\n var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;\n var isGlobal = container == this.gloMod;\n\n var signature: Signature = new Signature();\n var isLambda = funcDecl.fncFlags & FncFlags.IsFunctionExpression;\n\n // If a return type has been declared for the signature, set the type link.\n // Otherwise:\n // if it's a signature, its type will be 'any'\n // if it's a definition, the return type will be inferred \n if (funcDecl.returnTypeAnnotation || isDefinition) {\n signature.returnType = getTypeLink(funcDecl.returnTypeAnnotation, this, false);\n }\n else {\n signature.returnType = new TypeLink();\n signature.returnType.type = this.anyType;\n }\n\n signature.hasVariableArgList = funcDecl.variableArgList;\n\n var sigData = this.getParameterList(funcDecl, container);\n\n signature.parameters = sigData.parameters;\n signature.nonOptionalParameterCount = sigData.nonOptionalParameterCount;\n\n funcDecl.signature = signature;\n signature.declAST = funcDecl;\n\n var useOverloadGroupSym =\n overloadGroupSym &&\n overloadGroupSym.getType() &&\n !overloadGroupSym.isAccessor() &&\n (funcDecl.isSignature() || (isAmbient == hasFlag(overloadGroupSym.flags, SymbolFlags.Ambient)));\n\n if (useOverloadGroupSym && isPrivate != hasFlag(overloadGroupSym.flags, SymbolFlags.Private)) {\n this.errorReporter.simpleError(funcDecl, \"Public/Private visibility of overloads does not agree\");\n }\n\n var groupType = useOverloadGroupSym ? overloadGroupSym.getType() : new Type();\n\n if (isConstructor) {\n if (groupType.construct == null) {\n groupType.construct = new SignatureGroup();\n }\n groupType.construct.addSignature(signature);\n groupType.construct.hasImplementation = !(funcDecl.isSignature());\n if (groupType.construct.hasImplementation) {\n groupType.setHasImplementation();\n }\n }\n else if (funcDecl.isIndexerMember()) {\n if (groupType.index == null) {\n groupType.index = new SignatureGroup();\n groupType.index.flags |= SignatureFlags.IsIndexer;\n }\n\n groupType.index.addSignature(signature);\n groupType.index.hasImplementation = !(funcDecl.isSignature());\n if (groupType.index.hasImplementation) {\n groupType.setHasImplementation();\n }\n }\n else {\n if (groupType.call == null) {\n groupType.call = new SignatureGroup();\n }\n groupType.call.addSignature(signature);\n\n groupType.call.hasImplementation = !(funcDecl.isSignature());\n if (groupType.call.hasImplementation) {\n groupType.setHasImplementation();\n }\n }\n\n var instanceType = groupType.instanceType;\n\n // Ensure that the function's symbol is properly configured\n // (If there were overloads, we'll already have a symbol, otherwise we need to create one)\n var funcName: string = null;\n\n // Set the function's name:\n // In the case of anonymous or functions resulting from error\n // correction in the parser (isMissing() == true), we do not\n // want to set a function name, since they shouldn't be inserted\n // into the enclosing scope\n\n // usedHint prevents functions bound to object literal fields from being added to the\n // enclosing scope\n var usedHint = false;\n if (funcDecl.name && !funcDecl.name.isMissing()) {\n funcName = funcDecl.name.text;\n }\n else if (funcDecl.hint) {\n funcName = funcDecl.hint;\n usedHint = true;\n }\n\n if (groupType.symbol == null) {\n groupType.symbol =\n new TypeSymbol(funcName ? funcName : this.anon,\n funcDecl.minChar, funcDecl.limChar - funcDecl.minChar,\n this.locationInfo.unitIndex,\n groupType);\n if (!useOverloadGroupSym) {\n groupType.symbol.declAST = funcDecl;\n }\n }\n\n // REVIEW: Are we missing any other flags?\n if (isStatic) {\n groupType.symbol.flags |= SymbolFlags.Static;\n }\n\n if (isAmbient) {\n groupType.symbol.flags |= SymbolFlags.Ambient;\n }\n\n if (isPrivate) {\n groupType.symbol.flags |= SymbolFlags.Private;\n }\n\n groupType.symbol.isMethod = funcDecl.isMethod();\n if (groupType.symbol.isMethod) {\n groupType.symbol.flags |= SymbolFlags.Property;\n }\n\n funcDecl.type = groupType;\n\n // Add the function symbol to the appropriate scope\n // if the funcDecl is a constructor, it will be added to the enclosing scope as a class\n if (!isConstructor) {\n // Add the function's symbol to its enclosing scope\n if (funcName && !isLambda && !funcDecl.isAccessor() && !usedHint) {\n\n // REVIEW: We're not setting the isDecl flags for fuctions bound to object literal properties\n // so removing the isDefiniton clause would break object literals\n if (addToScope) { // REVIEW: If we combine this with createFunctionDeclarationSignature, we'll need to broaden this for both decls and defs \n // if it's a static method, enter directly into the container's scope\n if (funcDecl.isMethod() && isStatic) {\n\n // REVIEW: What about private statics?\n if (!(<TypeSymbol>container).type.members.publicMembers.add(funcName, groupType.symbol)) {\n this.errorReporter.duplicateIdentifier(funcDecl, funcName);\n }\n\n groupType.symbol.container = container;\n } // REVIEW: Another check for overloads...\n else if (overloadGroupSym == null || (overloadGroupSym.declAST && !(<FuncDecl>overloadGroupSym.declAST).isOverload && (container.isType()))) {\n scope.enter(container, funcDecl, groupType.symbol, this.errorReporter, !isPrivate && (isExported || isStatic || isGlobal), false, isAmbient);\n }\n }\n else if (!funcDecl.isSpecialFn()) {\n groupType.symbol.container = container; // REVIEW: Set container for overloads or anonymous?\n }\n }\n else if (!funcDecl.isSpecialFn()) {\n groupType.symbol.container = container; // REVIEW: Set container for lambdas and accessors?\n }\n }\n\n // If, say, a call signature overload was declared before the class type was, we want to reuse\n // the type that's already been instantiated for the class type, rather than allocate a new one\n if (useOverloadGroupSym) {\n var overloadGroupType = overloadGroupSym ? overloadGroupSym.getType() : null;\n var classType = groupType;\n\n if (classType != overloadGroupType) {\n if (classType.construct == null) {\n if (overloadGroupType && overloadGroupType.construct) {\n classType.construct = overloadGroupType.construct;\n }\n else {\n classType.construct = new SignatureGroup();\n }\n }\n else if (overloadGroupType) {\n if (overloadGroupType.construct) {\n classType.construct.signatures.concat(overloadGroupType.construct.signatures);\n }\n }\n\n // sync call and index signatures as well, but don't allocate should they not\n // already exist\n if (overloadGroupType) {\n if (classType.call == null) {\n classType.call = overloadGroupType.call;\n }\n else if (overloadGroupType.call) {\n classType.call.signatures.concat(overloadGroupType.call.signatures);\n }\n\n // if the function is not static, we need to add any call overloads onto the\n // instance type's call signature list\n if (!isStatic) {\n\n if (classType.instanceType == null) {\n classType.instanceType = overloadGroupType.instanceType;\n }\n\n var instanceType = classType.instanceType;\n\n if (instanceType) {\n if (instanceType.call == null) {\n instanceType.call = overloadGroupType.call;\n }\n else if (overloadGroupType.call) {\n instanceType.call.signatures.concat(overloadGroupType.call.signatures);\n }\n }\n }\n\n if (classType.index == null) {\n classType.index = overloadGroupType.index;\n }\n else if (overloadGroupType.index) {\n classType.index.signatures.concat(overloadGroupType.index.signatures);\n }\n }\n }\n }\n\n return signature;\n }\n\n // Creates a new symbol for an accessor property\n // Note that funcDecl.type.symbol and fgSym may not be the same (E.g., in the case of type collection)\n public createAccessorSymbol(funcDecl: FuncDecl, fgSym: Symbol, enclosingClass: Type, addToMembers: bool, isClassProperty: bool, scope: SymbolScope, container: Symbol) {\n var accessorSym: FieldSymbol = null\n var sig = funcDecl.signature;\n var nameText = funcDecl.name.text;\n var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);\n\n if (fgSym == null) {\n var field = new ValueLocation();\n accessorSym = new FieldSymbol(nameText, funcDecl.minChar, this.locationInfo.unitIndex, false, field);\n field.symbol = accessorSym;\n accessorSym.declAST = funcDecl; // REVIEW: need to reset for getters and setters\n\n if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n if (accessorSym.getter) {\n this.errorReporter.simpleError(funcDecl, \"Redeclaration of property getter\");\n }\n accessorSym.getter = <TypeSymbol>sig.declAST.type.symbol;\n }\n else {\n if (accessorSym.setter) {\n this.errorReporter.simpleError(funcDecl, \"Redeclaration of property setter\");\n }\n accessorSym.setter = <TypeSymbol>sig.declAST.type.symbol;\n }\n\n field.typeLink = getTypeLink(null, this, false);\n\n // if it's static, enter it into the class's member list directly\n if (addToMembers) {\n if (enclosingClass) {\n if (!enclosingClass.members.publicMembers.add(nameText, accessorSym)) {\n this.errorReporter.duplicateIdentifier(funcDecl, accessorSym.name);\n }\n accessorSym.container = enclosingClass.symbol;\n }\n else {\n this.errorReporter.simpleError(funcDecl, \"Accessor property may not be added in this context\");\n }\n }\n else {\n scope.enter(container, funcDecl, accessorSym, this.errorReporter, !isPrivate || isStatic, false, false);\n }\n\n // We set the flags here, instead of below, because the accessor symbol does not yet have a type\n if (isClassProperty) {\n accessorSym.flags |= SymbolFlags.Property;\n }\n if (isStatic) {\n accessorSym.flags |= SymbolFlags.Static;\n }\n\n if (isPrivate) {\n accessorSym.flags |= SymbolFlags.Private;\n }\n else {\n accessorSym.flags |= SymbolFlags.Public;\n }\n }\n else {\n accessorSym = <FieldSymbol>(<any>fgSym);\n\n if (isPrivate != hasFlag(accessorSym.flags, SymbolFlags.Private)) {\n this.errorReporter.simpleError(funcDecl, \"Getter and setter accessors do not agree in visibility\");\n }\n\n if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n if (accessorSym.getter) {\n this.errorReporter.simpleError(funcDecl, \"Redeclaration of property getter\");\n }\n accessorSym.getter = <TypeSymbol>funcDecl.type.symbol;\n }\n else {\n if (accessorSym.setter) {\n this.errorReporter.simpleError(funcDecl, \"Redeclaration of property setter\");\n }\n accessorSym.setter = <TypeSymbol>funcDecl.type.symbol;\n }\n }\n\n return accessorSym;\n }\n\n public addBases(resultScope: SymbolAggregateScope, type: Type, baseContext: { base: string; baseId: number; }): void {\n resultScope.addParentScope(new SymbolTableScope(type.members, type.ambientMembers, type.getAllEnclosedTypes(), type.getAllAmbientEnclosedTypes(), type.symbol));\n var i = 0;\n var parent: Type;\n if (type.extendsList) {\n for (var len = type.extendsList.length; i < len; i++) {\n parent = type.extendsList[i];\n if (baseContext.baseId == parent.typeID) {\n this.errorReporter.reportErrorFromSym(parent.symbol, \"Type '\" + baseContext.base + \"' is recursively referenced as a base class of itself\");\n parent.symbol.flags |= SymbolFlags.RecursivelyReferenced;\n break;\n }\n this.addBases(resultScope, parent, baseContext);\n }\n }\n }\n\n public scopeOf(type: Type): SymbolScope {\n var resultScope = new SymbolAggregateScope(type.symbol);\n var baseContext = { base: type.symbol && type.symbol.name ? type.symbol.name : \"{}\", baseId: type.typeID };\n this.addBases(resultScope, type, baseContext);\n return resultScope;\n }\n\n public lookupMemberTypeSymbol(containingType: Type, name: string): Symbol {\n var symbol: Symbol = null;\n if (containingType.containedScope) {\n symbol = containingType.containedScope.find(name, false, true);\n }\n else if (containingType.members) {\n symbol = containingType.members.allMembers.lookup(name);\n\n if (symbol == null && containingType.ambientMembers) {\n symbol = containingType.ambientMembers.allMembers.lookup(name);\n }\n }\n if (symbol == null) {\n var typeMembers = containingType.getAllEnclosedTypes();\n var ambientTypeMembers = containingType.getAllAmbientEnclosedTypes();\n if (typeMembers) {\n symbol = typeMembers.allMembers.lookup(name);\n\n if (symbol == null && ambientTypeMembers) {\n symbol = ambientTypeMembers.allMembers.lookup(name);\n }\n\n }\n }\n if (symbol && symbol.isType()) {\n return symbol;\n }\n else {\n return null;\n }\n }\n\n public findSymbolForDynamicModule(idText: string, currentFileName: string, search: (id: string) =>Symbol): Symbol {\n var originalIdText = idText;\n var symbol = search(idText);\n \n if (symbol == null) {\n // perhaps it's a dynamic module?\n if (!symbol) {\n idText = swapQuotes(originalIdText);\n symbol = search(idText);\n }\n\n // Check the literal path first\n if (!symbol) {\n idText = stripQuotes(originalIdText) + \".ts\";\n symbol = search(idText);\n }\n\n if (!symbol) {\n idText = stripQuotes(originalIdText) + \".str\";\n symbol = search(idText);\n }\n\n // Check check for .d.str\n if (!symbol) {\n idText = stripQuotes(originalIdText) + \".d.ts\";\n symbol = search(idText);\n }\n\n if (!symbol) {\n idText = stripQuotes(originalIdText) + \".d.str\";\n symbol = search(idText);\n }\n\n // If the literal path doesn't work, begin the search\n if (!symbol && !isRelative(originalIdText)) {\n // check the full path first, as this is the most likely scenario\n idText = originalIdText;\n\n var strippedIdText = stripQuotes(idText);\n\n // REVIEW: Technically, we shouldn't have to normalize here - we should normalize in addUnit.\n // Still, normalizing here alows any language services to be free of assumptions\n var path = getRootFilePath(switchToForwardSlashes(currentFileName));\n\n while (symbol == null && path != \"\") {\n idText = normalizePath(path + strippedIdText + \".ts\");\n symbol = search(idText);\n\n // check for .str\n if (symbol == null) {\n idText = changePathToSTR(idText);\n symbol = search(idText);\n }\n\n // check for .d.ts\n if (symbol == null) {\n idText = changePathToDTS(idText);\n symbol = search(idText);\n }\n\n // check for .d.str\n if (symbol == null) {\n idText = changePathToDSTR(idText);\n symbol = search(idText);\n }\n\n if (symbol == null) {\n if(path === '/') {\n path = '';\n } else {\n path = normalizePath(path + \"..\");\n path = path && path != '/' ? path + '/' : path;\n }\n }\n }\n }\n }\n\n return symbol;\n }\n\n public resolveTypeMember(scope: SymbolScope, dotNode: BinaryExpression): Type {\n var lhs = dotNode.operand1;\n var rhs = dotNode.operand2;\n var resultType = this.anyType;\n var lhsType = this.anyType;\n\n if (lhs && rhs && (rhs.nodeType == NodeType.Name)) {\n if (lhs.nodeType == NodeType.Dot) {\n lhsType = this.resolveTypeMember(scope, <BinaryExpression>lhs);\n }\n else if (lhs.nodeType == NodeType.Name) {\n var identifier = <Identifier>lhs;\n var symbol = scope.find(identifier.text, false, true);\n if (symbol == null) {\n this.errorReporter.unresolvedSymbol(identifier, identifier.actualText);\n }\n else if (symbol.isType()) {\n\n var typeSymbol = <TypeSymbol> symbol;\n\n if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {\n var modPath = (<Identifier>typeSymbol.aliasLink.alias).text;\n var modSym = this.findSymbolForDynamicModule(modPath, this.locationInfo.filename, (id) => scope.find(id, false, true));\n if (modSym) {\n typeSymbol.type = modSym.getType();\n }\n }\n\n if (optimizeModuleCodeGen && symbol) {\n var symType = symbol.getType();\n // Once the type has been referenced outside of a type ref position, there's\n // no going back \n if (symType && typeSymbol.aliasLink && typeSymbol.onlyReferencedAsTypeRef) {\n\n var modDecl = <ModuleDeclaration>symType.symbol.declAST;\n if (modDecl && hasFlag(modDecl.modFlags, ModuleFlags.IsDynamic)) {\n typeSymbol.onlyReferencedAsTypeRef = !this.resolvingBases;\n }\n }\n }\n if (!symbol.visible(scope, this)) {\n this.errorReporter.simpleError(lhs, \"The symbol '\" + identifier.actualText + \"' is not visible at this point\");\n }\n lhsType = symbol.getType();\n\n identifier.sym = symbol;\n }\n else {\n this.errorReporter.simpleError(lhs, \"Expected type\");\n }\n\n }\n\n // if the LHS type is a module alias, we won't be able to resolve it until\n // typecheck type. If this is called during binding, lhsType will be null\n if (!lhsType) {\n lhsType = this.anyType;\n }\n\n if (lhsType != this.anyType) {\n var rhsIdentifier = <Identifier>rhs;\n var resultSymbol = this.lookupMemberTypeSymbol(lhsType, rhsIdentifier.text);\n if (resultSymbol == null) {\n resultType = this.anyType;\n this.errorReporter.simpleError(dotNode, \"Expected type\");\n }\n else {\n resultType = resultSymbol.getType();\n if (!resultSymbol.visible(scope, this)) {\n this.errorReporter.simpleError(lhs, \"The symbol '\" + (<Identifier>rhs).actualText + \"' is not visible at this point\");\n }\n }\n rhsIdentifier.sym = resultType.symbol;\n }\n }\n if (resultType.isClass()) {\n resultType = resultType.instanceType;\n }\n return resultType;\n }\n\n public resolveFuncDecl(funcDecl: FuncDecl, scope: SymbolScope,\n fgSym: TypeSymbol): Symbol {\n var functionGroupSymbol = this.createFunctionSignature(funcDecl, scope.container, scope, fgSym, false).declAST.type.symbol;\n var signatures: Signature[];\n if (funcDecl.isConstructMember()) {\n signatures = functionGroupSymbol.type.construct.signatures;\n }\n else if (funcDecl.isIndexerMember()) {\n signatures = functionGroupSymbol.type.getInstanceType().index.signatures;\n }\n else {\n signatures = functionGroupSymbol.type.call.signatures;\n }\n\n var signature = signatures[signatures.length - 1];\n var len = signature.parameters.length;\n for (var i = 0; i < len; i++) {\n var paramSym: ParameterSymbol = signature.parameters[i];\n this.resolveTypeLink(scope, paramSym.parameter.typeLink, true);\n }\n\n // If a vararg list is present, check that the type is an array type\n if (len && funcDecl.variableArgList) {\n if (!signature.parameters[len - 1].parameter.typeLink.type.elementType) {\n this.errorReporter.simpleErrorFromSym(signature.parameters[len - 1].parameter.symbol, \"... parameter must have array type\");\n signature.parameters[len - 1].parameter.typeLink.type = this.makeArrayType(signature.parameters[len - 1].parameter.typeLink.type);\n }\n }\n this.resolveTypeLink(scope, signature.returnType,\n funcDecl.isSignature());\n return functionGroupSymbol;\n }\n\n public resolveVarDecl(varDecl: VarDecl, scope: SymbolScope): Symbol {\n var field = new ValueLocation();\n var fieldSymbol =\n new FieldSymbol(varDecl.id.text, varDecl.minChar, this.locationInfo.unitIndex,\n (varDecl.varFlags & VarFlags.Readonly) == VarFlags.None,\n field);\n fieldSymbol.transferVarFlags(varDecl.varFlags);\n field.symbol = fieldSymbol;\n fieldSymbol.declAST = varDecl;\n field.typeLink = getTypeLink(varDecl.typeExpr, this, varDecl.init == null);\n this.resolveTypeLink(scope, field.typeLink, true);\n varDecl.sym = fieldSymbol;\n varDecl.type = field.typeLink.type;\n return fieldSymbol;\n }\n\n public resolveTypeLink(scope: SymbolScope, typeLink: TypeLink, supplyVar: bool): void {\n var arrayCount = 0;\n if (typeLink.type == null) {\n var ast: AST = typeLink.ast;\n if (ast) {\n while (typeLink.type == null) {\n switch (ast.nodeType) {\n case NodeType.Name:\n var identifier = <Identifier>ast;\n var symbol = scope.find(identifier.text, false, true);\n if (symbol == null) {\n typeLink.type = this.anyType;\n this.errorReporter.unresolvedSymbol(identifier, identifier.actualText);\n }\n else if (symbol.isType()) {\n if (!symbol.visible(scope, this)) {\n this.errorReporter.simpleError(ast, \"The symbol '\" + identifier.actualText + \"' is not visible at this point\");\n }\n identifier.sym = symbol;\n typeLink.type = symbol.getType();\n if (typeLink.type) {\n if (typeLink.type.isClass()) {\n typeLink.type = typeLink.type.instanceType;\n }\n }\n else {\n typeLink.type = this.anyType;\n }\n }\n else {\n typeLink.type = this.anyType;\n this.errorReporter.simpleError(ast, \"Expected type\");\n }\n break;\n case NodeType.Dot:\n typeLink.type = this.resolveTypeMember(scope, <BinaryExpression>ast);\n break;\n case NodeType.TypeRef:\n var typeRef = <TypeReference>ast;\n arrayCount = typeRef.arrayCount;\n ast = typeRef.term;\n if (ast == null) {\n typeLink.type = this.anyType;\n }\n break;\n case NodeType.InterfaceDeclaration:\n var interfaceDecl = <InterfaceDeclaration>ast;\n var interfaceType = new Type();\n var interfaceSymbol = new TypeSymbol((<Identifier>interfaceDecl.name).text,\n ast.minChar,\n ast.limChar - ast.minChar,\n this.locationInfo.unitIndex,\n interfaceType);\n interfaceType.symbol = interfaceSymbol;\n interfaceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n interfaceType.containedScope =\n new SymbolTableScope(interfaceType.members, null, null, null,\n interfaceSymbol);\n\n interfaceType.containedScope.container = interfaceSymbol;\n interfaceType.memberScope = interfaceType.containedScope;\n\n var memberList = <ASTList>interfaceDecl.members;\n var props: AST[] = memberList.members;\n var propsLen = props.length;\n\n for (var j = 0; j < propsLen; j++) {\n var propDecl = props[j];\n var propSym: Symbol = null;\n var addMember = true;\n var id: Identifier = null;\n if (propDecl.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>propDecl;\n id = funcDecl.name;\n propSym = interfaceType.members.allMembers.lookup(funcDecl.getNameText());\n addMember = (propSym == null);\n if (funcDecl.isSpecialFn()) {\n addMember = false;\n propSym = this.resolveFuncDecl(funcDecl, scope, interfaceSymbol);\n }\n else {\n propSym = this.resolveFuncDecl(funcDecl, scope, <TypeSymbol>propSym);\n }\n funcDecl.type = (<TypeSymbol>propSym).type;\n }\n else {\n id = (<VarDecl>propDecl).id;\n propSym = this.resolveVarDecl(<VarDecl>propDecl, scope);\n\n // Don't add the member if it was missing a name. This \n // generally just leads to cascading errors that make things\n // more confusing for the user.\n addMember = !id.isMissing();\n }\n\n if (addMember) {\n if (id && hasFlag(id.flags, ASTFlags.OptionalName)) {\n propSym.flags |= SymbolFlags.Optional;\n }\n if (!interfaceType.members.allMembers.add(propSym.name, propSym)) {\n this.errorReporter.duplicateIdentifier(ast, propSym.name);\n }\n }\n }\n\n ast.type = interfaceType;\n typeLink.type = interfaceType;\n\n break;\n case NodeType.FuncDecl:\n var tsym = <TypeSymbol>this.resolveFuncDecl(<FuncDecl>ast, scope, null);\n typeLink.type = tsym.type;\n break;\n default:\n typeLink.type = this.anyType;\n this.errorReporter.simpleError(ast, \"Expected type\");\n break;\n }\n }\n }\n for (var count = arrayCount; count > 0; count--) {\n typeLink.type = this.makeArrayType(typeLink.type);\n }\n if (supplyVar && (typeLink.type == null)) {\n typeLink.type = this.anyType;\n }\n if (typeLink.ast) {\n typeLink.ast.type = typeLink.type;\n }\n }\n // else wait for type inference\n }\n\n public resolveBaseTypeLink(typeLink: TypeLink, scope: SymbolScope) {\n this.resolvingBases = true;\n this.resolveTypeLink(scope, typeLink, true);\n this.resolvingBases = false;\n var extendsType: Type = null;\n if (typeLink.type.isClass()) {\n extendsType = typeLink.type.instanceType;\n }\n else {\n extendsType = typeLink.type;\n }\n\n return extendsType;\n }\n\n public findMostApplicableSignature(signatures: ApplicableSignature[], args: ASTList): { sig: Signature; ambiguous: bool; } {\n\n if (signatures.length == 1) {\n return { sig: signatures[0].signature, ambiguous: false };\n }\n\n var best: ApplicableSignature = signatures[0];\n var Q: ApplicableSignature = null;\n var AType: Type = null;\n var PType: Type = null;\n var QType: Type = null;\n var ambiguous = false;\n\n for (var qSig = 1; qSig < signatures.length; qSig++) {\n Q = signatures[qSig];\n var i = 0;\n // find the better conversion\n for (i = 0; args && i < args.members.length; i++) {\n AType = args.members[i].type;\n PType = i < best.signature.parameters.length ? best.signature.parameters[i].getType() : best.signature.parameters[best.signature.parameters.length - 1].getType().elementType;\n QType = i < Q.signature.parameters.length ? Q.signature.parameters[i].getType() : Q.signature.parameters[Q.signature.parameters.length - 1].getType().elementType;\n\n if (this.typesAreIdentical(PType, QType)) {\n continue;\n }\n else if (this.typesAreIdentical(AType, PType)) {\n break;\n }\n else if (this.typesAreIdentical(AType, QType)) {\n best = Q;\n break;\n }\n else if (this.sourceIsSubtypeOfTarget(PType, QType)) {\n break;\n }\n else if (this.sourceIsSubtypeOfTarget(QType, PType)) {\n best = Q;\n break;\n }\n else if (Q.hadProvisionalErrors) {\n break;\n }\n else if (best.hadProvisionalErrors) {\n best = Q;\n break;\n }\n }\n\n if (!args || i == args.members.length) {\n var collection: ITypeCollection = {\n getLength: () => { return 2; },\n setTypeAtIndex: (index: number, type: Type) => { }, // no contextual typing here, so no need to do anything\n getTypeAtIndex: (index: number) => { return index ? Q.signature.returnType.type : best.signature.returnType.type; } // we only want the \"second\" type - the \"first\" is skipped\n }\n var bct = this.findBestCommonType(best.signature.returnType.type, null, collection, true);\n ambiguous = !bct;\n }\n else {\n ambiguous = false;\n }\n }\n\n return { sig: best.signature, ambiguous: ambiguous };\n }\n\n public getApplicableSignatures(signatures: Signature[], args: ASTList, comparisonInfo: TypeComparisonInfo): ApplicableSignature[] {\n\n var applicableSigs: ApplicableSignature[] = [];\n var memberType: Type = null;\n var miss = false;\n var cxt: ContextualTypeContext = null;\n var hadProvisionalErrors = false;\n\n for (var i = 0; i < signatures.length; i++) {\n miss = false;\n\n for (var j = 0; j < args.members.length; j++) {\n\n if (j >= signatures[i].parameters.length) {\n continue;\n }\n memberType = signatures[i].parameters[j].getType();\n\n // account for varargs\n if (signatures[i].declAST.variableArgList && (j >= signatures[i].nonOptionalParameterCount - 1) && memberType.isArray()) {\n memberType = memberType.elementType;\n }\n\n if (memberType == this.anyType) {\n continue;\n }\n else if (args.members[j].nodeType == NodeType.FuncDecl) {\n if (this.typeFlow.functionInterfaceType && memberType == this.typeFlow.functionInterfaceType) {\n continue;\n }\n if (!this.canContextuallyTypeFunction(memberType, <FuncDecl>args.members[j], true)) {\n // if it's just annotations that are blocking us, typecheck the function and add it to the list\n if (this.canContextuallyTypeFunction(memberType, <FuncDecl>args.members[j], false)) {\n this.typeFlow.typeCheck(args.members[j]);\n if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n break;\n }\n }\n else {\n break;\n }\n }\n else { // if it can be contextually typed, try it out...\n\n this.typeCheckWithContextualType(memberType, true, true, args.members[j]);\n this.cleanStartedPTO();\n hadProvisionalErrors = this.hadProvisionalErrors();\n\n if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n if (comparisonInfo) {\n comparisonInfo.setMessage(\"Could not apply type '\" + memberType.getTypeName() + \"' to argument \" + (j + 1) + \", which is of type '\" + args.members[j].type.getTypeName() + \"'\");\n }\n miss = true;\n }\n\n // clean the type\n //if (hadProvisionalErrors) {\n // cxt = this.currentContextualTypeContext;\n // this.typeCheckWithContextualType(null, true, true, args.members[j]);\n // if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType)) {\n // miss = true;\n // }\n // this.cleanStartedPTO();\n //}\n\n this.resetProvisionalErrors();\n if (miss) {\n break;\n }\n }\n }\n else if (args.members[j].nodeType == NodeType.ObjectLit) {\n // now actually attempt to typecheck as the contextual type\n if (this.typeFlow.objectInterfaceType && memberType == this.typeFlow.objectInterfaceType) {\n continue;\n }\n\n this.typeCheckWithContextualType(memberType, true, true, args.members[j]);\n this.cleanStartedPTO();\n hadProvisionalErrors = this.hadProvisionalErrors(); \n\n if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n if (comparisonInfo) {\n comparisonInfo.setMessage(\"Could not apply type '\" + memberType.getTypeName() + \"' to argument \" + (j + 1) + \", which is of type '\" + args.members[j].type.getTypeName() + \"'\");\n }\n miss = true;\n }\n\n // clean the type\n //if (hadProvisionalErrors) {\n // this.typeCheckWithContextualType(null, true, true, args.members[j]);\n\n // // is the \"cleaned\" type even assignable?\n // if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType)) {\n // miss = true;\n // }\n\n // this.cleanStartedPTO();\n //}\n\n this.resetProvisionalErrors();\n if (miss) {\n break;\n }\n }\n else if (args.members[j].nodeType == NodeType.ArrayLit) {\n // attempt to contextually type the array literal\n if (this.typeFlow.arrayInterfaceType && memberType == this.typeFlow.arrayInterfaceType) {\n continue;\n }\n\n this.typeCheckWithContextualType(memberType, true, true, args.members[j]);\n this.cleanStartedPTO();\n hadProvisionalErrors = this.hadProvisionalErrors(); \n\n if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n if (comparisonInfo) {\n comparisonInfo.setMessage(\"Could not apply type '\" + memberType.getTypeName() + \"' to argument \" + (j + 1) + \", which is of type '\" + args.members[j].type.getTypeName() + \"'\");\n }\n break;\n }\n\n // clean the type\n //if (hadProvisionalErrors) {\n // this.typeCheckWithContextualType(null, true, true, args.members[j]);\n // if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType)) {\n // miss = true;\n // }\n\n // this.cleanStartedPTO();\n //}\n\n this.resetProvisionalErrors();\n if (miss) {\n break;\n }\n }\n }\n\n if (j == args.members.length) {\n applicableSigs[applicableSigs.length] = { signature: signatures[i], hadProvisionalErrors: hadProvisionalErrors };\n }\n hadProvisionalErrors = false;\n }\n\n return applicableSigs;\n }\n\n public canContextuallyTypeFunction(candidateType: Type, funcDecl: FuncDecl, beStringent: bool): bool {\n\n // in these cases, we do not attempt to apply a contextual type\n // RE: isInlineCallLiteral - if the call target is a function literal, we don't want to apply the target type\n // to its body - instead, it should be applied to its return type\n if (funcDecl.isParenthesized ||\n funcDecl.isMethod() ||\n beStringent && funcDecl.returnTypeAnnotation ||\n funcDecl.isInlineCallLiteral) {\n return false;\n }\n\n beStringent = beStringent || (this.typeFlow.functionInterfaceType == candidateType);\n\n // At this point, if we're not being stringent, there's no need to check for multiple call sigs\n // or count parameters - we just want to unblock typecheck\n if (!beStringent) {\n return true;\n }\n\n // If we're coming from an in-scope typecheck, lambdas may not have had function signatures created for them\n // REVIEW: Should we search out the overload group here?\n if (!funcDecl.signature) {\n this.createFunctionSignature(funcDecl, this.typeFlow.scope.container, this.typeFlow.scope, null, null);\n this.typeFlow.typeCheck(funcDecl);\n }\n\n var signature = funcDecl.signature;\n var paramLen = signature.parameters.length;\n\n // Check that the argument declarations have no type annotations\n for (var i = 0; i < paramLen; i++) {\n var param = signature.parameters[i];\n var symbol = <ParameterSymbol>param;\n var argDecl = <ArgDecl>symbol.declAST;\n\n // REVIEW: a valid typeExpr is a requirement for varargs,\n // so we may want to revise our invariant\n if (beStringent && argDecl.typeExpr) {\n return false;\n }\n }\n\n if (candidateType.construct && candidateType.call) {\n return false;\n }\n\n var candidateSigs = candidateType.construct ? candidateType.construct : candidateType.call;\n\n if (!candidateSigs || candidateSigs.signatures.length > 1) {\n return false;\n }\n\n // if we're here, the contextual type can be applied to the function\n return true;\n }\n\n public canContextuallyTypeObjectLiteral(targetType: Type, objectLit: UnaryExpression): bool {\n\n if (targetType == this.typeFlow.objectInterfaceType) {\n return true;\n }\n\n var memberDecls = <ASTList>objectLit.operand;\n\n if (!(memberDecls && targetType.memberScope)) {\n return false;\n }\n\n var id: AST = null;\n var targetMember: Symbol = null;\n var text = \"\";\n var foundSyms = {};\n\n // Check that each property in the object literal is present in the target\n // type\n for (var i = 0; i < memberDecls.members.length; i++) {\n id = (<BinaryExpression>memberDecls.members[i]).operand1;\n\n if (id.nodeType == NodeType.Name) {\n text = (<Identifier>id).text;\n }\n else if (id.nodeType == NodeType.QString) {\n // TODO: set text to unescaped string\n var idText = (<StringLiteral>id).text;\n text = idText.substring(1, idText.length - 1);\n }\n else {\n return false;\n }\n\n targetMember = targetType.memberScope.find(text, true, false);\n\n if (!targetMember) {\n return false;\n }\n\n foundSyms[text] = true;\n }\n\n // Check that all members in the target type are present in the object literal\n var targetMembers = targetType.memberScope.getAllValueSymbolNames(true);\n\n for (var i = 0; i < targetMembers.length; i++) {\n var memberName = targetMembers[i];\n var memberSym = targetType.memberScope.find(memberName, true, false);\n\n if (!foundSyms[targetMembers[i]] &&\n !hasFlag(memberSym.flags, SymbolFlags.Optional)) {\n return false;\n }\n }\n\n return true;\n }\n\n public widenType(t: Type) {\n if (t == this.undefinedType || t == this.nullType) { // REVIEW: not isNullOrUndefinedType for perf reasons\n return this.anyType;\n }\n\n return t;\n }\n\n public isNullOrUndefinedType(t: Type) {\n return t == this.undefinedType || t == this.nullType;\n }\n\n public findBestCommonType(initialType: Type, targetType: Type, collection: ITypeCollection, acceptVoid:bool, comparisonInfo?: TypeComparisonInfo) {\n var i = 0;\n var len = collection.getLength();\n var nlastChecked = 0;\n var bestCommonType = initialType;\n\n if (targetType) {\n bestCommonType = bestCommonType ? bestCommonType.mergeOrdered(targetType, this, acceptVoid) : targetType;\n }\n\n // it's important that we set the convergence type here, and not in the loop,\n // since the first element considered may be the contextual type\n var convergenceType: Type = bestCommonType;\n\n while (nlastChecked < len) {\n\n for (i = 0; i < len; i++) {\n\n // no use in comparing a type against itself\n if (i == nlastChecked) {\n continue;\n }\n\n if (convergenceType && (bestCommonType = convergenceType.mergeOrdered(collection.getTypeAtIndex(i), this, acceptVoid, comparisonInfo))) {\n convergenceType = bestCommonType;\n }\n\n if (bestCommonType == this.anyType || bestCommonType == null) {\n break;\n }\n else if (targetType) { // set the element type to the target type\n collection.setTypeAtIndex(i, targetType);\n }\n }\n\n // use the type if we've agreed upon it\n if (convergenceType && bestCommonType) {\n break;\n }\n\n nlastChecked++;\n if (nlastChecked < len) {\n convergenceType = collection.getTypeAtIndex(nlastChecked);\n }\n }\n\n return acceptVoid ? bestCommonType : (bestCommonType == this.voidType ? null : bestCommonType);\n }\n\n // Type Identity\n\n public typesAreIdentical(t1: Type, t2: Type) {\n\n // This clause will cover both primitive types (since the type objects are shared),\n // as well as shared brands\n if (t1 == t2) {\n return true;\n }\n\n if (!t1 || !t2) {\n return false;\n }\n\n if (t1.isClass() || t1.isClassInstance()) {\n return false;\n }\n\n var comboId = (t2.typeID << 16) | t1.typeID;\n\n if (this.identicalCache[comboId]) {\n return true;\n }\n\n // If one is an enum, and they're not the same type, they're not identical\n if ((t1.typeFlags & TypeFlags.IsEnum) || (t2.typeFlags & TypeFlags.IsEnum)) {\n return false;\n }\n\n if (t1.isArray() || t2.isArray()) {\n if (!(t1.isArray() && t2.isArray())) {\n return false;\n }\n this.identicalCache[comboId] = false;\n var ret = this.typesAreIdentical(t1.elementType, t2.elementType);\n if (ret) {\n this.subtypeCache[comboId] = true;\n }\n else {\n this.subtypeCache[comboId] = undefined;\n }\n\n return ret;\n }\n\n if (t1.primitiveTypeClass != t2.primitiveTypeClass) {\n return false;\n }\n\n this.identicalCache[comboId] = false;\n\n // properties are identical in name, optionality, and type\n // REVIEW: TypeChanges - The compiler does not currently check against the members of parent types!\n // REVIEW: TypeChanges - What about ambientMembers?\n if (t1.memberScope && t2.memberScope) {\n var t1MemberKeys = t1.memberScope.getAllValueSymbolNames(true).sort();\n var t2MemberKeys = t2.memberScope.getAllValueSymbolNames(true).sort();\n\n if (t1MemberKeys.length != t2MemberKeys.length) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n var t1MemberSymbol: Symbol = null;\n var t2MemberSymbol: Symbol = null;\n\n var t1MemberType: Type = null;\n var t2MemberType: Type = null;\n\n for (var iMember = 0; iMember < t1MemberKeys.length; iMember++) {\n if (t1MemberKeys[iMember] != t2MemberKeys[iMember]) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n t1MemberSymbol = <Symbol>t1.memberScope.find(t1MemberKeys[iMember], false, false);\n t2MemberSymbol = <Symbol>t2.memberScope.find(t2MemberKeys[iMember], false, false);\n\n if ((t1MemberSymbol.flags & SymbolFlags.Optional) != (t2MemberSymbol.flags & SymbolFlags.Optional)) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n t1MemberType = t1MemberSymbol.getType();\n t2MemberType = t2MemberSymbol.getType();\n\n // catch the mutually recursive or cached cases\n if (t1MemberType && t2MemberType && (this.identicalCache[(t2MemberType.typeID << 16) | t1MemberType.typeID] != undefined)) {\n continue;\n }\n\n if (!this.typesAreIdentical(t1MemberType, t2MemberType)) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n }\n }\n else if (t1.memberScope || t2.memberScope) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n if (!this.signatureGroupsAreIdentical(t1.call, t2.call)) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n if (!this.signatureGroupsAreIdentical(t1.construct, t2.construct)) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n if (!this.signatureGroupsAreIdentical(t1.index, t2.index)) {\n this.identicalCache[comboId] = undefined;\n return false;\n }\n\n this.identicalCache[comboId] = true;\n return true;\n }\n\n public signatureGroupsAreIdentical(sg1: SignatureGroup, sg2: SignatureGroup) {\n\n // covers the null case\n if (sg1 == sg2) {\n return true;\n }\n\n // covers the mixed-null case\n if (!sg1 || !sg2) {\n return false;\n }\n\n if (sg1.signatures.length != sg2.signatures.length) {\n return false;\n }\n\n var sig1: Signature = null;\n var sig2: Signature = null;\n var sigsMatch = false;\n\n // The signatures in the signature group may not be ordered...\n // REVIEW: Should definition signatures be required to be identical as well?\n for (var iSig1 = 0; iSig1 < sg1.signatures.length; iSig1++) {\n sig1 = sg1.signatures[iSig1];\n\n for (var iSig2 = 0; iSig2 < sg2.signatures.length; iSig2++) {\n sig2 = sg2.signatures[iSig2];\n\n if (this.signaturesAreIdentical(sig1, sig2)) {\n sigsMatch = true;\n break;\n }\n }\n\n if (sigsMatch) {\n sigsMatch = false;\n continue;\n }\n\n // no match found for a specific signature\n return false;\n }\n\n return true;\n }\n\n public signaturesAreIdentical(s1: Signature, s2: Signature) {\n\n if (s1.hasVariableArgList != s2.hasVariableArgList) {\n return false;\n }\n\n if (s1.nonOptionalParameterCount != s2.nonOptionalParameterCount) {\n return false;\n }\n\n if (s1.parameters.length != s2.parameters.length) {\n return false;\n }\n\n if (!this.typesAreIdentical(s1.returnType.type, s2.returnType.type)) {\n return false;\n }\n\n for (var iParam = 0; iParam < s1.parameters.length; iParam++) {\n if (!this.typesAreIdentical(s1.parameters[iParam].parameter.typeLink.type, s2.parameters[iParam].parameter.typeLink.type)) {\n return false;\n }\n }\n\n return true;\n }\n\n // Subtyping and Assignment compatibility\n\n public sourceIsSubtypeOfTarget(source: Type, target: Type, comparisonInfo?: TypeComparisonInfo) { return this.sourceIsRelatableToTarget(source, target, false, this.subtypeCache, comparisonInfo); }\n public signatureGroupIsSubtypeOfTarget(sg1: SignatureGroup, sg2: SignatureGroup, comparisonInfo?: TypeComparisonInfo) { return this.signatureGroupIsRelatableToTarget(sg1, sg2, false, this.subtypeCache, comparisonInfo); }\n public signatureIsSubtypeOfTarget(s1: Signature, s2: Signature, comparisonInfo?: TypeComparisonInfo) { return this.signatureIsRelatableToTarget(s1, s2, false, this.subtypeCache, comparisonInfo); }\n\n public sourceIsAssignableToTarget(source: Type, target: Type, comparisonInfo?: TypeComparisonInfo) { return this.sourceIsRelatableToTarget(source, target, true, this.assignableCache, comparisonInfo); }\n public signatureGroupIsAssignableToTarget(sg1: SignatureGroup, sg2: SignatureGroup, comparisonInfo?: TypeComparisonInfo) { return this.signatureGroupIsRelatableToTarget(sg1, sg2, true, this.assignableCache, comparisonInfo); }\n public signatureIsAssignableToTarget(s1: Signature, s2: Signature, comparisonInfo?: TypeComparisonInfo) { return this.signatureIsRelatableToTarget(s1, s2, true, this.assignableCache, comparisonInfo); }\n\n public sourceIsRelatableToTarget(source: Type, target: Type, assignableTo: bool, comparisonCache: any, comparisonInfo: TypeComparisonInfo) {\n\n // REVIEW: Does this check even matter?\n //if (this.typesAreIdentical(source, target)) {\n // return true;\n //}\n if (source == target) {\n return true;\n }\n\n // An error has already been reported in this case\n if (!(source && target)) {\n return true;\n }\n\n var comboId = (source.typeID << 16) | target.typeID;\n\n // In the case of a 'false', we want to short-circuit a recursive typecheck\n if (comparisonCache[comboId] != undefined) {\n return true;\n }\n\n // this is one difference between subtyping and assignment compatibility\n if (assignableTo) {\n if (source == this.anyType || target == this.anyType) {\n return true;\n }\n }\n else {\n // This is one difference between assignment compatibility and subtyping\n if (target == this.anyType) {\n return true;\n }\n }\n\n if (source == this.undefinedType) {\n return true;\n }\n\n if ((source == this.nullType) && (target != this.undefinedType && target != this.voidType)) {\n return true;\n }\n\n // REVIEW: enum types aren't explicitly covered in the spec\n if (target == this.numberType && (source.typeFlags & TypeFlags.IsEnum)) {\n return true;\n }\n if (source == this.numberType && (target.typeFlags & TypeFlags.IsEnum)) {\n return true;\n }\n if ((source.typeFlags & TypeFlags.IsEnum) || (target.typeFlags & TypeFlags.IsEnum)) {\n return false;\n }\n\n if (source.isArray() || target.isArray()) {\n if (!(source.isArray() && target.isArray())) {\n return false;\n }\n comparisonCache[comboId] = false;\n var ret = this.sourceIsRelatableToTarget(source.elementType, target.elementType, assignableTo, comparisonCache, comparisonInfo);\n if (ret) {\n comparisonCache[comboId] = true;\n }\n else {\n comparisonCache[comboId] = undefined;\n }\n\n return ret;\n }\n\n // this check ensures that we only operate on object types from this point forward,\n // since the checks involving primitives occurred above\n if (source.primitiveTypeClass != target.primitiveTypeClass) {\n\n if (target.primitiveTypeClass == Primitive.None) {\n if (source == this.numberType && this.typeFlow.numberInterfaceType) {\n source = this.typeFlow.numberInterfaceType;\n }\n else if (source == this.stringType && this.typeFlow.stringInterfaceType) {\n source = this.typeFlow.stringInterfaceType;\n }\n else if (source == this.booleanType && this.typeFlow.booleanInterfaceType) {\n source = this.typeFlow.booleanInterfaceType;\n }\n else {\n return false;\n }\n }\n else {\n return false;\n }\n }\n\n comparisonCache[comboId] = false;\n\n if (source.hasBase(target)) {\n comparisonCache[comboId] = true;\n return true;\n }\n\n if (this.typeFlow.objectInterfaceType && target == this.typeFlow.objectInterfaceType) {\n return true;\n }\n\n if (this.typeFlow.functionInterfaceType && (source.call || source.construct) && target == this.typeFlow.functionInterfaceType) {\n return true;\n }\n\n // REVIEW: We should perhaps do this, though it wouldn't be quite right without generics support\n //if (this.typeFlow.arrayInterfaceType && (source.index) && target == this.typeFlow.arrayInterfaceType) {\n // return true;\n //}\n\n // At this point, if the target is a class, but not the source or a parent of the source, bail\n if (target.isClass() || target.isClassInstance()) {\n comparisonCache[comboId] = undefined;\n return false;\n }\n\n if (target.memberScope && source.memberScope) {\n var mPropKeys = target.memberScope.getAllValueSymbolNames(true);\n var mProp: Symbol = null;\n var nProp: Symbol = null;\n var mPropType: Type = null;\n var nPropType: Type = null;\n var inferenceSymbol: InferenceSymbol = null;\n\n for (var iMProp = 0; iMProp < mPropKeys.length; iMProp++) {\n mProp = target.memberScope.find(mPropKeys[iMProp], false, false);\n nProp = source.memberScope.find(mPropKeys[iMProp], false, false);\n\n // methods do not have the \"arguments\" field\n if (mProp.name == \"arguments\" &&\n this.typeFlow.iargumentsInterfaceType &&\n (this.typeFlow.iargumentsInterfaceType.symbol.flags & SymbolFlags.CompilerGenerated) &&\n mProp.kind() == SymbolKind.Variable &&\n (<VariableSymbol>mProp).variable.typeLink.type == this.typeFlow.iargumentsInterfaceType) {\n continue;\n }\n\n if (mProp.isInferenceSymbol()) {\n inferenceSymbol = <InferenceSymbol>mProp;\n if (inferenceSymbol.typeCheckStatus == TypeCheckStatus.NotStarted) {\n // REVIEW: TypeChanges: Does this ever really happen? Maybe for out-of-order typecheck?\n this.typeFlow.typeCheck(mProp.declAST);\n }\n }\n mPropType = mProp.getType();\n\n if (!nProp) {\n // If it's not present on the type in question, look for the property on 'Object'\n if (this.typeFlow.objectInterfaceType) {\n nProp = this.typeFlow.objectInterfaceType.memberScope.find(mPropKeys[iMProp], false, false);\n }\n\n if (!nProp) {\n // Now, the property was not found on Object, but the type in question is a function, look\n // for it on function\n if (this.typeFlow.functionInterfaceType && (mPropType.call || mPropType.construct)) {\n nProp = this.typeFlow.functionInterfaceType.memberScope.find(mPropKeys[iMProp], false, false);\n }\n\n // finally, check to see if the property is optional\n if (!nProp) {\n if (!(mProp.flags & SymbolFlags.Optional)) {\n comparisonCache[comboId] = undefined;\n if (comparisonInfo) { // only surface the first error\n comparisonInfo.flags |= TypeRelationshipFlags.RequiredPropertyIsMissing;\n comparisonInfo.addMessageToFront(\"Type '\" + source.getTypeName() + \"' is missing property '\" + mPropKeys[iMProp] + \"' from type '\" + target.getTypeName() + \"'\");\n }\n return false;\n }\n else {\n continue;\n }\n }\n }\n }\n\n if (nProp.isInferenceSymbol()) {\n inferenceSymbol = <InferenceSymbol>nProp;\n if (inferenceSymbol.typeCheckStatus == TypeCheckStatus.NotStarted) {\n this.typeFlow.typeCheck(nProp.declAST);\n }\n }\n\n\n nPropType = nProp.getType();\n\n // catch the mutually recursive or cached cases\n if (mPropType && nPropType && (comparisonCache[(nPropType.typeID << 16) | mPropType.typeID] != undefined)) {\n continue;\n }\n\n if (!this.sourceIsRelatableToTarget(nPropType, mPropType, assignableTo, comparisonCache, comparisonInfo)) {\n comparisonCache[comboId] = undefined;\n if (comparisonInfo) { // only surface the first error\n comparisonInfo.flags |= TypeRelationshipFlags.IncompatiblePropertyTypes;\n comparisonInfo.addMessageToFront(\"Types of property '\" + mProp.name + \"' of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n }\n return false;\n }\n }\n }\n\n // check signature groups\n if (source.call || target.call) {\n if (!this.signatureGroupIsRelatableToTarget(source.call, target.call, assignableTo, comparisonCache, comparisonInfo)) {\n if (comparisonInfo) {\n if (source.call && target.call) {\n comparisonInfo.addMessageToFront(\"Call signatures of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n }\n else {\n var hasSig = target.call ? target.getTypeName() : source.getTypeName();\n var lacksSig = !target.call ? target.getTypeName() : source.getTypeName();\n comparisonInfo.setMessage(\"Type '\" + hasSig + \"' requires a call signature, but Type '\" + lacksSig + \"' lacks one\");\n }\n comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleSignatures;\n }\n comparisonCache[comboId] = undefined;\n return false;\n }\n }\n\n if (source.construct || target.construct) {\n if (!this.signatureGroupIsRelatableToTarget(source.construct, target.construct, assignableTo, comparisonCache, comparisonInfo)) {\n if (comparisonInfo) {\n if (source.construct && target.construct) {\n comparisonInfo.addMessageToFront(\"Construct signatures of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n }\n else {\n var hasSig = target.construct ? target.getTypeName() : source.getTypeName();\n var lacksSig = !target.construct ? target.getTypeName() : source.getTypeName();\n comparisonInfo.setMessage(\"Type '\" + hasSig + \"' requires a construct signature, but Type '\" + lacksSig + \"' lacks one\");\n }\n comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleSignatures;\n }\n comparisonCache[comboId] = undefined;\n return false;\n }\n }\n\n if (target.index) {\n var targetIndex = !target.index && this.typeFlow.objectInterfaceType ? this.typeFlow.objectInterfaceType.index : target.index;\n var sourceIndex = !source.index && this.typeFlow.objectInterfaceType ? this.typeFlow.objectInterfaceType.index : source.index;\n\n if (!this.signatureGroupIsRelatableToTarget(sourceIndex, targetIndex, assignableTo, comparisonCache, comparisonInfo)) {\n if (comparisonInfo) {\n comparisonInfo.addMessageToFront(\"Index signatures of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleSignatures;\n }\n comparisonCache[comboId] = undefined;\n return false;\n }\n }\n\n comparisonCache[comboId] = true;\n return true;\n }\n\n // REVIEW: TypeChanges: Return an error context object so the user can get better diagnostic info\n public signatureGroupIsRelatableToTarget(sourceSG: SignatureGroup, targetSG: SignatureGroup, assignableTo: bool, comparisonCache: any, comparisonInfo?: TypeComparisonInfo) {\n if (sourceSG == targetSG) {\n return true;\n }\n\n if (!(sourceSG && targetSG)) {\n return false;\n }\n\n var mSig: Signature = null;\n var nSig: Signature = null;\n var foundMatch = false;\n\n for (var iMSig = 0; iMSig < targetSG.signatures.length; iMSig++) {\n mSig = targetSG.signatures[iMSig];\n\n for (var iNSig = 0; iNSig < sourceSG.signatures.length; iNSig++) {\n nSig = sourceSG.signatures[iNSig];\n if (this.signatureIsRelatableToTarget(nSig, mSig, assignableTo, comparisonCache, comparisonInfo)) {\n foundMatch = true;\n break;\n }\n }\n\n if (foundMatch) {\n foundMatch = false;\n continue;\n }\n return false;\n }\n\n return true;\n }\n\n public signatureIsRelatableToTarget(sourceSig: Signature, targetSig: Signature, assignableTo: bool, comparisonCache: any, comparisonInfo?: TypeComparisonInfo) {\n\n if (!sourceSig.parameters || !targetSig.parameters) {\n return false;\n }\n\n var targetVarArgCount = targetSig.hasVariableArgList ? targetSig.nonOptionalParameterCount - 1 : targetSig.nonOptionalParameterCount;\n var sourceVarArgCount = sourceSig.hasVariableArgList ? sourceSig.nonOptionalParameterCount - 1 : sourceSig.nonOptionalParameterCount;\n\n if (sourceVarArgCount > targetVarArgCount && !targetSig.hasVariableArgList) {\n if (comparisonInfo) {\n comparisonInfo.flags |= TypeRelationshipFlags.SourceSignatureHasTooManyParameters;\n comparisonInfo.addMessageToFront(\"Call signature expects \" + targetVarArgCount + \" or fewer parameters\");\n }\n return false;\n }\n\n var sourceReturnType = sourceSig.returnType.type;\n var targetReturnType = targetSig.returnType.type;\n\n if (targetReturnType != this.voidType) {\n if (!this.sourceIsRelatableToTarget(sourceReturnType, targetReturnType, assignableTo, comparisonCache, comparisonInfo)) {\n if (comparisonInfo) {\n comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleReturnTypes;\n // No need to print this one here - it's printed as part of the signature error in sourceIsRelatableToTarget\n //comparisonInfo.addMessageToFront(\"Incompatible return types: '\" + sourceReturnType.getTypeName() + \"' and '\" + targetReturnType.getTypeName() + \"'\");\n }\n return false;\n }\n }\n\n var len = (sourceVarArgCount < targetVarArgCount && sourceSig.hasVariableArgList) ? targetVarArgCount : sourceVarArgCount;\n var sourceParamType: Type = null;\n var targetParamType: Type = null;\n var sourceParamName = \"\";\n var targetParamName = \"\";\n\n for (var iSource = 0, iTarget = 0; iSource < len; iSource++, iTarget++) {\n\n if (!sourceSig.hasVariableArgList || iSource < sourceVarArgCount) {\n sourceParamType = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.typeLink.type;\n sourceParamName = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.symbol.name;\n }\n else if (iSource == sourceVarArgCount) {\n sourceParamType = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.typeLink.type;\n if (sourceParamType.elementType) {\n sourceParamType = sourceParamType.elementType;\n }\n sourceParamName = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.symbol.name;\n }\n\n if (iTarget < targetSig.parameters.length && iTarget < targetVarArgCount) {\n targetParamType = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.typeLink.type;\n targetParamName = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.symbol.name;\n }\n else if (targetSig.hasVariableArgList && iTarget == targetVarArgCount) {\n targetParamType = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.typeLink.type;\n if (targetParamType.elementType) {\n targetParamType = targetParamType.elementType;\n }\n targetParamName = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.symbol.name;\n }\n\n if (!(this.sourceIsRelatableToTarget(sourceParamType, targetParamType, assignableTo, comparisonCache, comparisonInfo) ||\n this.sourceIsRelatableToTarget(targetParamType, sourceParamType, assignableTo, comparisonCache, comparisonInfo))) {\n\n if (comparisonInfo) {\n comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleParameterTypes;\n }\n return false;\n }\n }\n return true;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class Continuation {\n public exceptionBlock = -1;\n constructor (public normalBlock: number) { }\n }\n\n function getBaseTypeLinks(bases: ASTList, baseTypeLinks: TypeLink[]) {\n if (bases) {\n var len = bases.members.length;\n if (baseTypeLinks == null) {\n baseTypeLinks = new TypeLink[];\n }\n for (var i = 0; i < len; i++) {\n var baseExpr = bases.members[i];\n var name = baseExpr;\n var typeLink = new TypeLink();\n typeLink.ast = name;\n baseTypeLinks[baseTypeLinks.length] = typeLink;\n }\n }\n return baseTypeLinks;\n }\n\n function getBases(type: Type, typeDecl: TypeDeclaration) {\n type.extendsTypeLinks = getBaseTypeLinks(typeDecl.extendsList, type.extendsTypeLinks);\n type.implementsTypeLinks = getBaseTypeLinks(typeDecl.implementsList, type.implementsTypeLinks);\n }\n\n function addPrototypeField(classType: Type, ast: AST, context: TypeCollectionContext) {\n var field = new ValueLocation();\n field.typeLink = new TypeLink();\n field.typeLink.ast = ast;\n field.typeLink.type = classType.instanceType;\n\n var fieldSymbol =\n new FieldSymbol(\"prototype\", ast.minChar,\n context.checker.locationInfo.unitIndex, true, field);\n fieldSymbol.flags |= (SymbolFlags.Property | SymbolFlags.BuiltIn);\n field.symbol = fieldSymbol;\n fieldSymbol.declAST = ast;\n classType.members.addPublicMember(\"prototype\", fieldSymbol);\n }\n\n export function createNewConstructGroupForType(type: Type) {\n var signature = new Signature();\n signature.returnType = new TypeLink();\n signature.returnType.type = type.instanceType;\n signature.parameters = [];\n\n type.construct = new SignatureGroup();\n type.construct.addSignature(signature); \n }\n\n export function cloneParentConstructGroupForChildType(child: Type, parent: Type) {\n child.construct = new SignatureGroup();\n var sig: Signature = null;\n\n if (!parent.construct) {\n createNewConstructGroupForType(parent);\n }\n\n for (var i = 0; i < parent.construct.signatures.length; i++) { \n sig = new Signature();\n sig.parameters = parent.construct.signatures[i].parameters;\n sig.nonOptionalParameterCount = parent.construct.signatures[i].nonOptionalParameterCount;\n sig.typeCheckStatus = parent.construct.signatures[i].typeCheckStatus;\n sig.declAST = parent.construct.signatures[i].declAST;\n sig.returnType = new TypeLink();\n sig.returnType.type = child.instanceType;\n child.construct.addSignature(sig);\n }\n\n }\n\n export var globalId = \"__GLO\";\n\n export interface IAliasScopeContext {\n topLevelScope: ScopeChain;\n members: IHashTable;\n tcContext: TypeCollectionContext;\n }\n\n function findTypeSymbolInScopeChain(name: string, scopeChain: ScopeChain): Symbol {\n var symbol = scopeChain.scope.find(name, false, true);\n\n if (symbol == null && scopeChain.previous) {\n symbol = findTypeSymbolInScopeChain(name, scopeChain.previous);\n }\n\n return symbol;\n }\n\n function findSymbolFromAlias(alias: AST, context: IAliasScopeContext): Symbol {\n var symbol: Symbol = null;\n switch (alias.nodeType) {\n case NodeType.Name:\n var name = (<Identifier>alias).text;\n var isDynamic = isQuoted(name);\n\n var findSym = (id: string) => {\n if (context.members) {\n return context.members.lookup(name);\n }\n else {\n return findTypeSymbolInScopeChain(name, context.topLevelScope);\n }\n }\n\n if (isDynamic) {\n symbol = context.tcContext.checker.findSymbolForDynamicModule(name, context.tcContext.script.locationInfo.filename, findSym);\n }\n else {\n symbol = findSym(name);\n }\n\n break;\n\n case NodeType.Dot:\n var dottedExpr = <BinaryExpression>alias;\n var op1Sym = findSymbolFromAlias(dottedExpr.operand1, context);\n\n if (op1Sym && op1Sym.getType()) {\n symbol = findSymbolFromAlias(dottedExpr.operand2, context);\n }\n\n break;\n\n default:\n break;\n }\n\n if (symbol) {\n var symType = symbol.getType();\n if (symType) {\n var members = symType.members;\n if (members) {\n context.members = members.publicMembers;\n }\n }\n }\n\n return symbol;\n }\n\n export function preCollectImportTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n var typeSymbol: TypeSymbol = null;\n var modType: ModuleType = null;\n var importDecl = <ImportDeclaration>ast;\n\n // REVIEW: technically, this call isn't strictly necessary, since we'll find the type during the call to resolveTypeMembers\n var aliasedModSymbol = findSymbolFromAlias(importDecl.alias, { topLevelScope: scopeChain, members: null, tcContext: context });\n var isGlobal = context.scopeChain.container == context.checker.gloMod;\n\n if (aliasedModSymbol) {\n var aliasedModType = aliasedModSymbol.getType();\n\n if (aliasedModType) {\n modType = <ModuleType>aliasedModType;\n }\n }\n\n typeSymbol = new TypeSymbol(importDecl.id.text, importDecl.id.minChar, importDecl.limChar - importDecl.minChar,\n context.checker.locationInfo.unitIndex, modType);\n\n typeSymbol.aliasLink = importDecl;\n\n if (context.scopeChain.moduleDecl) {\n typeSymbol.flags |= SymbolFlags.ModuleMember;\n typeSymbol.declModule = context.scopeChain.moduleDecl;\n }\n\n typeSymbol.declAST = importDecl;\n importDecl.id.sym = typeSymbol;\n scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isGlobal, true, false);\n scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isGlobal, false, false);\n return true;\n }\n\n export function preCollectModuleTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n\n var moduleDecl: ModuleDeclaration = <ModuleDeclaration>ast;\n\n var isAmbient = hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient);\n var isEnum = hasFlag(moduleDecl.modFlags, ModuleFlags.IsEnum);\n var isGlobal = context.scopeChain.container == context.checker.gloMod;\n var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);\n var modName = (<Identifier>moduleDecl.name).text;\n\n var isDynamic = isQuoted(modName);\n\n var symbol = scopeChain.scope.findLocal(modName, false, false);\n var typeSymbol: TypeSymbol = null;\n var modType: ModuleType = null;\n if ((symbol == null) || (symbol.kind() != SymbolKind.Type)) {\n\n if (modType == null) {\n var enclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);\n if (isEnum) {\n modType.typeFlags |= TypeFlags.IsEnum;\n }\n modType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n modType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n modType.setHasImplementation();\n }\n\n typeSymbol = new TypeSymbol(modName, moduleDecl.name.minChar, modName.length,\n context.checker.locationInfo.unitIndex, modType);\n typeSymbol.isDynamic = isQuoted(moduleDecl.prettyName);\n\n if (context.scopeChain.moduleDecl) {\n typeSymbol.declModule = context.scopeChain.moduleDecl;\n }\n typeSymbol.declAST = moduleDecl;\n typeSymbol.prettyName = moduleDecl.prettyName;\n scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isExported || isGlobal, true, isAmbient);\n scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isExported || isGlobal, false, isAmbient);\n modType.symbol = typeSymbol;\n }\n else {\n if (symbol && symbol.declAST && symbol.declAST.nodeType != NodeType.ModuleDeclaration) {\n context.checker.errorReporter.simpleError(moduleDecl, \"Conflicting symbol name for module '\" + modName + \"'\");\n }\n typeSymbol = <TypeSymbol>symbol;\n\n // initialize new private scope for the type\n var publicEnclosedTypes = typeSymbol.type.getAllEnclosedTypes().publicMembers;\n var publicEnclosedTypesTable = (publicEnclosedTypes == null) ? new StringHashTable() : publicEnclosedTypes;\n var enclosedTypes = new ScopedMembers(new DualStringHashTable(publicEnclosedTypesTable, new StringHashTable()));\n\n var publicEnclosedAmbientTypes = typeSymbol.type.getAllAmbientEnclosedTypes().publicMembers;\n var publicAmbientEnclosedTypesTable = (publicEnclosedAmbientTypes == null) ? new StringHashTable() : publicEnclosedAmbientTypes;\n var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(publicAmbientEnclosedTypesTable, new StringHashTable()));\n\n var publicMembers = typeSymbol.type.members.publicMembers;\n var publicMembersTable = (publicMembers == null) ? new StringHashTable() : publicMembers;\n var members = new ScopedMembers(new DualStringHashTable(publicMembersTable, new StringHashTable()));\n\n var publicAmbientMembers = typeSymbol.type.ambientMembers.publicMembers;\n var publicAmbientMembersTable = (publicAmbientMembers == null) ? new StringHashTable() : publicAmbientMembers;\n var ambientMembers = new ScopedMembers(new DualStringHashTable(publicAmbientMembersTable, new StringHashTable()));\n\n modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);\n if (isEnum) {\n modType.typeFlags |= TypeFlags.IsEnum;\n }\n modType.members = members;\n modType.ambientMembers = ambientMembers;\n modType.setHasImplementation();\n modType.symbol = typeSymbol;\n\n typeSymbol.addLocation(moduleDecl.minChar);\n typeSymbol.expansions.push(modType);\n typeSymbol.expansionsDeclAST.push(moduleDecl);\n\n }\n if (context.scopeChain.moduleDecl) {\n context.scopeChain.moduleDecl.recordNonInterface();\n }\n // REVIEW: If multiple disparate module decls for the same module don't agree\n // in export privileges, how should we handle it?\n if (isExported) {\n typeSymbol.flags |= SymbolFlags.Exported;\n }\n if ((context.scopeChain.moduleDecl) ||\n (context.scopeChain.container == context.checker.gloMod)) {\n typeSymbol.flags |= SymbolFlags.ModuleMember;\n }\n\n moduleDecl.mod = modType;\n pushTypeCollectionScope(typeSymbol, modType.members,\n modType.ambientMembers,\n modType.enclosedTypes,\n modType.ambientEnclosedTypes,\n context, null, null, moduleDecl);\n\n return true;\n }\n\n export function preCollectClassTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n var classDecl = <ClassDeclaration>ast;\n\n var classType: Type;\n var instanceType: Type;\n var typeSymbol: TypeSymbol = null;\n var className = (<Identifier>classDecl.name).text;\n var alreadyInScope = false;\n var isAmbient = hasFlag(classDecl.varFlags, VarFlags.Ambient);\n var isExported = hasFlag(classDecl.varFlags, VarFlags.Exported);\n var isGlobal = context.scopeChain.container == context.checker.gloMod;\n var containerMod = <TypeSymbol>scopeChain.container;\n var foundValSymbol = false;\n\n typeSymbol = <TypeSymbol>scopeChain.scope.findLocal(className, false, true);\n \n // check the value space, since an override may have been declared with the type's name\n // REVIEW-CLASSES\n if (!typeSymbol) {\n var valTypeSymbol = scopeChain.scope.findLocal(className, false, false);\n \n if (valTypeSymbol &&\n valTypeSymbol.isType() &&\n valTypeSymbol.declAST &&\n valTypeSymbol.declAST.nodeType == NodeType.FuncDecl &&\n (<FuncDecl>valTypeSymbol.declAST).isSignature()) {\n \n typeSymbol = <TypeSymbol>valTypeSymbol;\n foundValSymbol = true;\n \n if (isExported) {\n typeSymbol.flags |= SymbolFlags.Exported;\n }\n \n if (isAmbient) {\n typeSymbol.flags |= SymbolFlags.Ambient;\n } \n \n // the class was never entered into type space, so add it\n context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isExported || isGlobal, true, isAmbient); \n }\n }\n \n if (typeSymbol && !foundValSymbol && (typeSymbol.declAST != classDecl)) {\n typeSymbol = null;\n }\n\n if (typeSymbol == null) {\n var valueSymbol = scopeChain.scope.findLocal(className, false, false);\n classType = new Type();\n classType.setHasImplementation();\n instanceType = new Type();\n instanceType.setHasImplementation();\n classType.instanceType = instanceType;\n classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n addPrototypeField(classType, classDecl, context);\n instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n instanceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n typeSymbol = new TypeSymbol(className, classDecl.name.minChar, className.length,\n context.checker.locationInfo.unitIndex, classType);\n typeSymbol.declAST = classDecl;\n typeSymbol.instanceType = instanceType;\n classType.symbol = typeSymbol;\n instanceType.symbol = typeSymbol;\n\n if (context.scopeChain.moduleDecl) {\n context.scopeChain.moduleDecl.recordNonInterface();\n typeSymbol.declModule = context.scopeChain.moduleDecl;\n typeSymbol.flags |= SymbolFlags.ModuleMember;\n }\n\n if (isExported) {\n typeSymbol.flags |= SymbolFlags.Exported;\n }\n \n if (isAmbient) {\n typeSymbol.flags |= SymbolFlags.Ambient;\n }\n\n ast.type = classType;\n\n // class in both name spaces (type for instance type; constructor representative in value space)\n context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isExported || isGlobal, true, isAmbient);\n\n if (valueSymbol == null) {\n context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,\n context.checker.errorReporter, isExported || isGlobal, false, isAmbient);\n }\n }\n else { \n classType = typeSymbol.type;\n \n // If the instance type is null, a call overload was likely declared before the class constructor\n if (classType.instanceType == null) {\n classType.instanceType = new Type();\n classType.instanceType.setHasImplementation();\n classType.instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n classType.instanceType.symbol = classType.symbol;\n classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n }\n \n instanceType = classType.instanceType;\n ast.type = classType;\n }\n \n // if the class has no declared constructor, either create a default signature or adapt \n // it's base class's signature group\n if (!classDecl.constructorDecl) {\n\n if (typeSymbol && typeSymbol.declAST && typeSymbol.declAST.type && typeSymbol.declAST.type.call && !(<FuncDecl>typeSymbol.declAST).isOverload) {\n context.checker.errorReporter.duplicateIdentifier(typeSymbol.declAST, typeSymbol.name);\n }\n\n createNewConstructGroupForType(classDecl.type);\n }\n\n classType.typeFlags |= TypeFlags.IsClass;\n instanceType.typeFlags |= TypeFlags.IsClass;\n\n getBases(instanceType, classDecl);\n pushTypeCollectionScope(typeSymbol, instanceType.members, instanceType.ambientMembers, null, null,\n context, instanceType, classType, null);\n return true;\n }\n\n export function preCollectInterfaceTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n var interfaceDecl = <InterfaceDeclaration>ast;\n var interfaceSymbol: TypeSymbol = null;\n var interfaceType: Type = null;\n var isExported = hasFlag(interfaceDecl.varFlags, VarFlags.Exported);\n var isGlobal = context.scopeChain.container == context.checker.gloMod;\n var alreadyInScope = true;\n\n alreadyInScope = false;\n var interfaceName = (<Identifier>interfaceDecl.name).text;\n interfaceSymbol = <TypeSymbol>scopeChain.scope.findLocal(interfaceName, false, true);\n if (interfaceSymbol == null) {\n interfaceType = new Type();\n interfaceSymbol = new TypeSymbol(interfaceName,\n interfaceDecl.name.minChar,\n interfaceName.length,\n context.checker.locationInfo.unitIndex,\n interfaceType);\n interfaceType.symbol = interfaceSymbol;\n // REVIEW: Shouldn't allocate another table for interface privates\n interfaceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n interfaceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n interfaceSymbol.declAST = interfaceDecl;\n interfaceSymbol.declModule = context.scopeChain.moduleDecl;\n }\n else {\n alreadyInScope = true;\n interfaceType = interfaceSymbol.type;\n }\n\n if (!interfaceType) {\n interfaceType = context.checker.anyType;\n }\n\n ast.type = interfaceType;\n getBases(interfaceType, interfaceDecl);\n\n if (isExported) {\n interfaceSymbol.flags |= SymbolFlags.Exported;\n }\n\n if (context.scopeChain.moduleDecl) {\n interfaceSymbol.flags |= SymbolFlags.ModuleMember;\n }\n\n if (!alreadyInScope) {\n context.scopeChain.scope.enter(context.scopeChain.container, ast,\n interfaceSymbol, context.checker.errorReporter, isGlobal || isExported, true, false); // REVIEW: Technically, interfaces should be ambient\n }\n pushTypeCollectionScope(interfaceSymbol, interfaceType.members, interfaceType.ambientMembers, null, null,\n context, interfaceType, null, null);\n return true;\n }\n\n export function preCollectArgDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n var argDecl = <ArgDecl>ast;\n if (hasFlag(argDecl.varFlags, VarFlags.Public | VarFlags.Private)) {\n var field = new ValueLocation();\n var isPrivate = hasFlag(argDecl.varFlags, VarFlags.Private);\n var fieldSymbol =\n new FieldSymbol(argDecl.id.text, argDecl.id.minChar,\n context.checker.locationInfo.unitIndex,\n !hasFlag(argDecl.varFlags, VarFlags.Readonly),\n field);\n fieldSymbol.transferVarFlags(argDecl.varFlags);\n field.symbol = fieldSymbol;\n fieldSymbol.declAST = ast;\n argDecl.parameterPropertySym = fieldSymbol;\n\n context.scopeChain.scope.enter(context.scopeChain.container, ast,\n fieldSymbol, context.checker.errorReporter, !isPrivate, false, false);\n\n field.typeLink = getTypeLink(argDecl.typeExpr, context.checker, argDecl.init == null);\n argDecl.sym = fieldSymbol;\n }\n return false;\n }\n\n export function preCollectVarDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n var varDecl = <VarDecl>ast;\n var isAmbient = hasFlag(varDecl.varFlags, VarFlags.Ambient);\n var isExported = hasFlag(varDecl.varFlags, VarFlags.Exported);\n var isGlobal = context.scopeChain.container == context.checker.gloMod;\n var isProperty = hasFlag(varDecl.varFlags, VarFlags.Property);\n var isStatic = hasFlag(varDecl.varFlags, VarFlags.Static);\n var isPrivate = hasFlag(varDecl.varFlags, VarFlags.Private);\n var isOptional = hasFlag(varDecl.id.flags, ASTFlags.OptionalName);\n\n if (context.scopeChain.moduleDecl) {\n context.scopeChain.moduleDecl.recordNonInterface();\n }\n if (isProperty ||\n isExported ||\n (context.scopeChain.container == context.checker.gloMod) ||\n context.scopeChain.moduleDecl) {\n if (isAmbient) {\n var existingSym =\n <FieldSymbol>scopeChain.scope.findLocal(varDecl.id.text, false, false);\n if (existingSym) {\n varDecl.sym = existingSym;\n return false;\n }\n }\n\n // Defensive error detection...\n if (varDecl.id == null) {\n context.checker.errorReporter.simpleError(varDecl, \"Expected variable identifier at this location\");\n return false;\n }\n\n var field = new ValueLocation();\n var fieldSymbol =\n new FieldSymbol(varDecl.id.text, varDecl.id.minChar,\n context.checker.locationInfo.unitIndex,\n (varDecl.varFlags & VarFlags.Readonly) == VarFlags.None,\n field);\n fieldSymbol.transferVarFlags(varDecl.varFlags);\n if (isOptional) {\n fieldSymbol.flags |= SymbolFlags.Optional;\n }\n field.symbol = fieldSymbol;\n fieldSymbol.declAST = ast;\n if ((context.scopeChain.moduleDecl) ||\n (context.scopeChain.container == context.checker.gloMod)) {\n fieldSymbol.flags |= SymbolFlags.ModuleMember;\n fieldSymbol.declModule = context.scopeChain.moduleDecl;\n }\n\n // if it's static, enter it into the class's member list directly\n if (hasFlag(varDecl.varFlags, VarFlags.Property) && isStatic && context.scopeChain.classType) {\n if (!context.scopeChain.classType.members.publicMembers.add(varDecl.id.text, fieldSymbol)) {\n context.checker.errorReporter.duplicateIdentifier(ast, fieldSymbol.name);\n }\n fieldSymbol.container = context.scopeChain.classType.symbol;\n }\n else {\n context.scopeChain.scope.enter(context.scopeChain.container,\n ast,\n fieldSymbol,\n context.checker.errorReporter,\n !isPrivate && (isProperty || isExported || isGlobal || isStatic),\n false,\n isAmbient);\n }\n\n if (hasFlag(varDecl.varFlags, VarFlags.Exported)) {\n fieldSymbol.flags |= SymbolFlags.Exported;\n }\n\n field.typeLink = getTypeLink(varDecl.typeExpr, context.checker,\n varDecl.init == null);\n varDecl.sym = fieldSymbol;\n }\n return false;\n }\n\n export function preCollectFuncDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n var scopeChain = context.scopeChain;\n\n // REVIEW: This will have to change when we move to \"export\"\n if (context.scopeChain.moduleDecl) {\n context.scopeChain.moduleDecl.recordNonInterface();\n }\n\n var funcDecl = <FuncDecl>ast;\n var fgSym: TypeSymbol = null;\n var nameText = funcDecl.getNameText();\n var isExported = hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported);\n var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);\n var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;\n var containerSym:TypeSymbol = <TypeSymbol> (((funcDecl.isMethod() && isStatic) || funcDecl.isAccessor()) && context.scopeChain.classType ? context.scopeChain.classType.symbol : context.scopeChain.container);\n var containerScope: SymbolScope = context.scopeChain.scope;\n var isGlobal = containerSym == context.checker.gloMod;\n var isOptional = funcDecl.name && hasFlag(funcDecl.name.flags, ASTFlags.OptionalName);\n var go = false;\n var foundSymbol = false; \n\n // If this is a class constructor, the \"container\" is actually the class declaration\n if (isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n containerSym = <TypeSymbol>containerSym.container;\n containerScope = scopeChain.previous.scope;\n }\n\n funcDecl.unitIndex = context.checker.locationInfo.unitIndex;\n \n // If the parent is the constructor, and this isn't an instance method, skip it.\n // That way, we'll set the type during scope assignment, and can be sure that the\n // function will be placed in the constructor-local scope\n if (!funcDecl.isConstructor &&\n containerSym &&\n containerSym.declAST &&\n containerSym.declAST.nodeType == NodeType.FuncDecl &&\n (<FuncDecl>containerSym.declAST).isConstructor &&\n !funcDecl.isMethod()) {\n return go;\n } \n\n // Interfaces and overloads\n if (hasFlag(funcDecl.fncFlags, FncFlags.Signature)) {\n var instType = context.scopeChain.thisType; \n\n // If the function is static, search in the class type's\n if (nameText && nameText != \"__missing\") {\n if (isStatic) {\n fgSym = containerSym.type.members.allMembers.lookup(nameText);\n }\n else {\n // REVIEW: This logic should be symmetric with preCollectClassTypes\n fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, false);\n \n // If we could not find the function symbol in the value context, look\n // in the type context.\n // This would be the case, for example, if a class constructor override\n // were declared before a call override for a given class\n if (fgSym == null) {\n fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, true);\n }\n }\n \n if (fgSym) {\n foundSymbol = true;\n \n // We'll combine ambient and non-ambient funcdecls during typecheck (for contextual typing).,\n // So, if they don't agree, don't use the symbol we've found \n if (!funcDecl.isSignature() && (hasFlag(funcDecl.fncFlags, FncFlags.Ambient) != hasFlag(fgSym.flags, SymbolFlags.Ambient))) {\n fgSym = null;\n }\n } \n }\n \n // a function with this symbol has not yet been declared in this scope\n // REVIEW: In the code below, we need to ensure that only function overloads are considered\n // (E.g., if a vardecl has the same id as a function or class, we may use the vardecl symbol\n // as the overload.) Defensively, however, the vardecl won't have a type yet, so it should\n // suffice to just check for a null type when considering the overload symbol in\n // createFunctionSignature\n if (fgSym == null) {\n if (!(funcDecl.isSpecialFn())) { \n fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, null, !foundSymbol).declAST.type.symbol;\n }\n else {\n fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, containerSym, false).declAST.type.symbol; \n }\n \n // set the symbol's declAST, which will point back to the first declaration (symbol or otherwise)\n // related to this symbol\n if (fgSym.declAST == null || !funcDecl.isSpecialFn()) {\n fgSym.declAST = ast;\n }\n }\n else { // there exists a symbol with this name\n \n if ((fgSym.kind() == SymbolKind.Type)) {\n\n fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, false).declAST.type.symbol;\n }\n else {\n context.checker.errorReporter.simpleError(funcDecl, \"Function or method '\" + funcDecl.name.actualText + \"' already declared as a property\");\n }\n }\n \n if (funcDecl.isSpecialFn() && !isStatic) {\n funcDecl.type = instType ? instType : fgSym.type; \n }\n else {\n funcDecl.type = fgSym.type;\n } \n }\n else {\n // declarations\n \n if (nameText) {\n if (isStatic) {\n fgSym = containerSym.type.members.allMembers.lookup(nameText);\n }\n else {\n // in the constructor case, we want to check the parent scope for overloads\n if (funcDecl.isConstructor && context.scopeChain.previous) {\n fgSym = <TypeSymbol>context.scopeChain.previous.scope.findLocal(nameText, false, false);\n }\n \n if (fgSym == null) {\n fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, false);\n }\n }\n if (fgSym) {\n foundSymbol = true;\n \n if (!isConstructor && fgSym.declAST.nodeType == NodeType.FuncDecl && !(<FuncDecl>fgSym.declAST).isAccessor() && !(<FuncDecl>fgSym.declAST).isSignature()) {\n fgSym = null;\n foundSymbol = false;\n }\n } \n }\n\n // REVIEW: Move this check into the typecheck phase? It's only being run over properties...\n if (fgSym &&\n !fgSym.isAccessor() &&\n fgSym.type &&\n fgSym.type.construct &&\n fgSym.type.construct.signatures != [] &&\n (fgSym.type.construct.signatures[0].declAST == null ||\n !hasFlag(fgSym.type.construct.signatures[0].declAST.fncFlags, FncFlags.Ambient)) &&\n !funcDecl.isConstructor) {\n context.checker.errorReporter.simpleError(funcDecl, \"Functions may not have class overloads\");\n }\n\n if (fgSym && !(fgSym.kind() == SymbolKind.Type) && funcDecl.isMethod() && !funcDecl.isAccessor() && !funcDecl.isConstructor) {\n context.checker.errorReporter.simpleError(funcDecl, \"Function or method '\" + funcDecl.name.actualText + \"' already declared as a property\");\n fgSym.type = context.checker.anyType;\n }\n var sig = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, !foundSymbol);\n\n // it's a getter or setter function \n if (((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) || (fgSym && fgSym.isAccessor())) {\n funcDecl.accessorSymbol = context.checker.createAccessorSymbol(funcDecl, fgSym, containerSym.type, (funcDecl.isMethod() && isStatic), true, containerScope, containerSym);\n }\n\n funcDecl.type.symbol.declAST = ast;\n if (funcDecl.isConstructor) { // REVIEW: Remove when classes completely replace oldclass\n go = true;\n };\n }\n if (isExported) {\n if (funcDecl.type.call) {\n funcDecl.type.symbol.flags |= SymbolFlags.Exported;\n }\n \n // Accessors are set to 'exported' above\n if (fgSym && !fgSym.isAccessor() && fgSym.kind() == SymbolKind.Type && fgSym.type.call) {\n fgSym.flags |= SymbolFlags.Exported;\n }\n }\n if (context.scopeChain.moduleDecl && !funcDecl.isSpecialFn()) {\n funcDecl.type.symbol.flags |= SymbolFlags.ModuleMember;\n funcDecl.type.symbol.declModule = context.scopeChain.moduleDecl;\n }\n\n if (fgSym && isOptional) {\n fgSym.flags |= SymbolFlags.Optional;\n }\n\n return go;\n }\n\n export function preCollectTypes(ast: AST, parent: AST, walker: IAstWalker) {\n var context: TypeCollectionContext = walker.state;\n var go = false;\n var scopeChain = context.scopeChain;\n\n if (ast.nodeType == NodeType.Script) {\n var script: Script = <Script>ast;\n context.script = script;\n go = true;\n }\n else if (ast.nodeType == NodeType.List) {\n go = true;\n }\n else if (ast.nodeType == NodeType.ImportDeclaration) {\n go = preCollectImportTypes(ast, parent, context);\n }\n else if (ast.nodeType == NodeType.With) {\n go = false;\n }\n else if (ast.nodeType == NodeType.ModuleDeclaration) {\n go = preCollectModuleTypes(ast, parent, context);\n }\n else if (ast.nodeType == NodeType.ClassDeclaration) {\n go = preCollectClassTypes(ast, parent, context);\n }\n else if (ast.nodeType == NodeType.Block) {\n go = true;\n }\n else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n go = preCollectInterfaceTypes(ast, parent, context);\n }\n // This will be a constructor arg because this pass only traverses\n // constructor arg lists\n else if (ast.nodeType == NodeType.ArgDecl) {\n go = preCollectArgDeclTypes(ast, parent, context);\n }\n else if (ast.nodeType == NodeType.VarDecl) {\n go = preCollectVarDeclTypes(ast, parent, context);\n }\n else if (ast.nodeType == NodeType.FuncDecl) {\n go = preCollectFuncDeclTypes(ast, parent, context);\n }\n else {\n if (ast.isStatementOrExpression() && context.scopeChain.moduleDecl) {\n context.scopeChain.moduleDecl.recordNonInterface();\n }\n }\n walker.options.goChildren = go;\n return ast;\n }\n\n export function postCollectTypes(ast: AST, parent: AST, walker: IAstWalker) {\n var context: TypeCollectionContext = walker.state;\n\n if (ast.nodeType == NodeType.ModuleDeclaration) {\n popTypeCollectionScope(context);\n }\n else if (ast.nodeType == NodeType.ClassDeclaration) {\n popTypeCollectionScope(context);\n }\n else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n popTypeCollectionScope(context);\n }\n return ast;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class ScopeChain {\n public thisType: Type;\n public classType: Type;\n public fnc: FuncDecl;\n public moduleDecl: ModuleDeclaration;\n\n constructor (public container: Symbol, public previous: ScopeChain,\n public scope: SymbolScope) { }\n }\n\n export class BBUseDefInfo {\n public defsBySymbol = new bool[];\n public gen: BitVector;\n public kill: BitVector;\n public top: BitVector;\n // use lists by symbol \n public useIndexBySymbol = new number[][];\n\n constructor (public bb: BasicBlock) { }\n\n public updateTop() {\n var temp = new BitVector(this.top.bitCount);\n for (var i = 0, succLen = this.bb.successors.length; i < succLen; i++) {\n var succ = this.bb.successors[i];\n if (succ.useDef) {\n temp.union(succ.useDef.top);\n }\n }\n temp.difference(this.kill);\n temp.union(this.gen);\n var changed = temp.notEq(this.top);\n this.top = temp;\n return changed;\n }\n\n\n public initialize(useDefContext: UseDefContext) {\n var defSym = (sym: Symbol, context: UseDefContext) => {\n if (context.isLocalSym(sym)) {\n var index = context.getSymbolIndex(sym);\n // clear pending uses\n this.useIndexBySymbol[index] = new number[];\n this.defsBySymbol[index] = true;\n }\n }\n\n var useSym = (sym: Symbol, context: UseDefContext, ast: AST) => {\n if (context.isLocalSym(sym)) {\n var symIndex = context.getSymbolIndex(sym);\n if (this.useIndexBySymbol[symIndex] == undefined) {\n this.useIndexBySymbol[symIndex] = new number[];\n }\n var symUses = this.useIndexBySymbol[symIndex];\n var astIndex = context.getUseIndex(ast);\n context.addUse(symIndex, astIndex);\n symUses.push(astIndex);\n }\n }\n\n function initUseDefPre(cur: AST, parent: AST, walker: IAstWalker) {\n var context: UseDefContext = walker.state;\n if (cur == null) {\n cur = null;\n }\n if (cur.nodeType == NodeType.VarDecl) {\n var varDecl = <BoundDecl>cur;\n if (varDecl.init || hasFlag(varDecl.varFlags, VarFlags.AutoInit)) {\n defSym(varDecl.sym, context);\n }\n }\n else if (cur.nodeType == NodeType.Name) {\n // use\n if (parent) {\n if (parent.nodeType == NodeType.Asg) {\n var asg = <BinaryExpression>parent;\n if (asg.operand1 == cur) {\n return cur;\n }\n }\n else if (parent.nodeType == NodeType.VarDecl) {\n var parentDecl = <BoundDecl>parent;\n if (parentDecl.id == cur) {\n return cur;\n }\n }\n }\n var id = <Identifier>cur;\n useSym(id.sym, context, cur);\n }\n else if ((cur.nodeType >= NodeType.Asg) && (cur.nodeType <= NodeType.LastAsg)) {\n // def\n var asg = <BinaryExpression>cur;\n if (asg.operand1 && (asg.operand1.nodeType == NodeType.Name)) {\n var id = <Identifier>asg.operand1;\n defSym(id.sym, context);\n }\n }\n else if (cur.nodeType == NodeType.FuncDecl) {\n walker.options.goChildren = false;\n }\n\n return cur;\n }\n\n var options = new AstWalkOptions();\n // traverse ASTs in reverse order of execution (to match uses with preceding defs)\n options.reverseSiblings = true;\n\n getAstWalkerFactory().walk(this.bb.content, initUseDefPre, null, options, useDefContext);\n }\n\n public initializeGen(useDefContext: UseDefContext) {\n var symbolLen = this.useIndexBySymbol.length;\n var bitCount = useDefContext.uses.length;\n this.gen = new BitVector(bitCount);\n for (var s = 0; s < symbolLen; s++) {\n var symUses = this.useIndexBySymbol[s];\n if ((symUses != undefined) && (symUses.length > 0)) {\n for (var u = 0, uLen = symUses.length; u < uLen; u++) {\n this.gen.set(symUses[u], true);\n }\n }\n }\n this.top = this.gen;\n }\n\n public initializeKill(useDefContext: UseDefContext) {\n this.kill = new BitVector(this.gen.bitCount);\n for (var s = 0, symbolLen = this.defsBySymbol.length; s < symbolLen; s++) {\n if (this.defsBySymbol[s]) {\n var globalSymUses = useDefContext.useIndexBySymbol[s];\n if (globalSymUses) {\n for (var u = 0, useLen = globalSymUses.length; u < useLen; u++) {\n this.kill.set(globalSymUses[u], true);\n }\n }\n }\n }\n }\n }\n\n export class UseDefContext {\n // global use lists by symbol\n public useIndexBySymbol = new number[][];\n // global list of uses (flat)\n public uses = new AST[];\n public symbols = new VariableSymbol[];\n public symbolMap = new StringHashTable();\n public symbolCount = 0;\n public func: Symbol;\n\n constructor () {\n }\n\n public getSymbolIndex(sym: Symbol) {\n var name = sym.name;\n var index = <number>(this.symbolMap.lookup(name));\n if (index == null) {\n index = this.symbolCount++;\n this.symbols[index] = <VariableSymbol>sym;\n this.symbolMap.add(name, index);\n }\n return index;\n }\n\n public addUse(symIndex: number, astIndex: number) {\n var useBySym = this.useIndexBySymbol[symIndex];\n if (useBySym == undefined) {\n useBySym = new number[];\n this.useIndexBySymbol[symIndex] = useBySym;\n }\n useBySym[useBySym.length] = astIndex;\n }\n\n public getUseIndex(ast: AST) {\n this.uses[this.uses.length] = ast;\n return this.uses.length - 1;\n }\n\n public isLocalSym(sym: Symbol) { return (sym && (sym.container == this.func) && (sym.kind() == SymbolKind.Variable)); }\n\n public killSymbol(sym: VariableSymbol, bbUses: BitVector) {\n var index: number = this.symbolMap.lookup(sym.name);\n var usesOfSym = this.useIndexBySymbol[index];\n for (var k = 0, len = usesOfSym.length; k < len; k++) {\n bbUses.set(usesOfSym[k], true);\n }\n }\n }\n\n export class BitVector {\n static packBits = 30;\n public firstBits = 0;\n public restOfBits: number[] = null;\n\n constructor (public bitCount: number) {\n if (this.bitCount > BitVector.packBits) {\n this.restOfBits = new number[];\n var len = Math.floor(this.bitCount / BitVector.packBits);\n for (var i = 0; i < len; i++) {\n this.restOfBits[i] = 0;\n }\n }\n }\n\n public set(bitIndex: number, value: bool) {\n if (bitIndex < BitVector.packBits) {\n if (value) {\n this.firstBits |= (1 << bitIndex);\n }\n else {\n this.firstBits &= (~(1 << bitIndex));\n }\n }\n else {\n var offset = Math.floor(bitIndex / BitVector.packBits) - 1;\n var localIndex = bitIndex % BitVector.packBits;\n if (value) {\n this.restOfBits[offset] |= (1 << localIndex);\n }\n else {\n this.restOfBits[offset] &= (~(1 << localIndex));\n }\n }\n }\n\n public map(fn: (index: number) =>any) {\n var k: number;\n for (k = 0; k < BitVector.packBits; k++) {\n if (k == this.bitCount) {\n return;\n }\n if (((1 << k) & this.firstBits) != 0) {\n fn(k);\n }\n }\n if (this.restOfBits) {\n var len: number;\n var cumu = BitVector.packBits;\n for (k = 0, len = this.restOfBits.length; k < len; k++) {\n var myBits = this.restOfBits[k];\n for (var j = 0; j < BitVector.packBits; j++) {\n if (((1 << j) & myBits) != 0) {\n fn(cumu);\n }\n cumu++;\n if (cumu == this.bitCount) {\n return;\n }\n }\n }\n }\n }\n\n // assume conforming sizes\n public union(b: BitVector) {\n this.firstBits |= b.firstBits;\n if (this.restOfBits) {\n for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n var myBits = this.restOfBits[k];\n var bBits = b.restOfBits[k];\n this.restOfBits[k] = myBits | bBits;\n }\n }\n }\n\n // assume conforming sizes\n public intersection(b: BitVector) {\n this.firstBits &= b.firstBits;\n if (this.restOfBits) {\n for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n var myBits = this.restOfBits[k];\n var bBits = b.restOfBits[k];\n this.restOfBits[k] = myBits & bBits;\n }\n }\n }\n\n // assume conforming sizes\n public notEq(b: BitVector) {\n if (this.firstBits != b.firstBits) {\n return true;\n }\n if (this.restOfBits) {\n for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n var myBits = this.restOfBits[k];\n var bBits = b.restOfBits[k];\n if (myBits != bBits) {\n return true;\n }\n }\n }\n return false;\n }\n\n public difference(b: BitVector) {\n var oldFirstBits = this.firstBits;\n this.firstBits &= (~b.firstBits);\n if (this.restOfBits) {\n for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n var myBits = this.restOfBits[k];\n var bBits = b.restOfBits[k];\n this.restOfBits[k] &= (~bBits);\n }\n }\n }\n }\n\n export class BasicBlock {\n // blocks that branch to the block after this one\n public predecessors = new BasicBlock[];\n public index = -1;\n public markValue = 0;\n public marked(markBase: number) { return this.markValue > markBase; }\n public mark() {\n this.markValue++;\n }\n public successors = new BasicBlock[];\n public useDef: BBUseDefInfo = null;\n public content = new ASTList();\n public addSuccessor(successor: BasicBlock): void {\n this.successors[this.successors.length] = successor;\n successor.predecessors[successor.predecessors.length] = this;\n }\n }\n\n export interface ITargetInfo {\n stmt: AST;\n continueBB: BasicBlock;\n breakBB: BasicBlock;\n }\n\n export class ControlFlowContext {\n public entry = null;\n // first unreachable ast for each unreachable code segment\n public unreachable: AST[] = null;\n public noContinuation = false;\n // statements enclosing the current statement\n public statementStack = new ITargetInfo[];\n public currentSwitch = new BasicBlock[];\n public walker: IAstWalker;\n\n constructor (public current: BasicBlock,\n public exit: BasicBlock) {\n this.entry = this.current;\n }\n\n public walk(ast: AST, parent: AST) {\n return this.walker.walk(ast, parent);\n }\n\n public pushSwitch(bb: BasicBlock) {\n this.currentSwitch.push(bb);\n }\n\n public popSwitch() {\n return this.currentSwitch.pop();\n }\n\n public reportUnreachable(er: ErrorReporter) {\n if (this.unreachable && (this.unreachable.length > 0)) {\n var len = this.unreachable.length;\n for (var i = 0; i < len; i++) {\n var unreachableAST = this.unreachable[i];\n if (unreachableAST.nodeType != NodeType.EndCode) {\n er.simpleError(unreachableAST, \"unreachable code\");\n }\n }\n }\n }\n\n private printAST(ast: AST, outfile: ITextWriter) {\n var printContext = new PrintContext(outfile, null);\n\n printContext.increaseIndent();\n //ast.walk(prePrintAST, postPrintAST, null, printContext);\n getAstWalkerFactory().walk(ast, prePrintAST, postPrintAST, null, printContext);\n\n printContext.decreaseIndent();\n }\n\n private printBlockContent(bb: BasicBlock, outfile: ITextWriter) {\n var content = bb.content;\n for (var i = 0, len = content.members.length; i < len; i++) {\n var ast = content.members[i];\n this.printAST(ast, outfile);\n }\n }\n\n public markBase = 0;\n\n public bfs(nodeFunc: (bb: BasicBlock) =>void , edgeFunc: (node1: BasicBlock, node2: BasicBlock) =>void ,\n preEdges: () =>void , postEdges: () =>void ) {\n var markValue = this.markBase++;\n var q = new BasicBlock[];\n q[q.length] = this.entry;\n\n while (q.length > 0) {\n var bb = q.pop();\n if (!(bb.marked(markValue))) {\n bb.mark();\n if (nodeFunc) {\n nodeFunc(bb);\n }\n var succLen = bb.successors.length;\n if (succLen > 0) {\n if (preEdges) {\n preEdges();\n }\n for (var j = succLen - 1; j >= 0; j--) {\n var successor = bb.successors[j];\n if (!(successor.marked(this.markBase))) {\n if (edgeFunc) {\n edgeFunc(bb, successor);\n }\n q[q.length] = successor;\n }\n }\n if (postEdges) {\n postEdges();\n }\n }\n }\n }\n }\n\n public linearBBs = new BasicBlock[];\n\n public useDef(er: ErrorReporter, funcSym: Symbol) {\n var useDefContext = new UseDefContext();\n useDefContext.func = funcSym;\n var useDefInit = (bb: BasicBlock) => {\n bb.useDef = new BBUseDefInfo(bb);\n bb.useDef.initialize(useDefContext);\n this.linearBBs[this.linearBBs.length] = bb;\n }\n this.bfs(useDefInit, null, null, null);\n var i: number, bbLen: number;\n for (i = 0, bbLen = this.linearBBs.length; i < bbLen; i++) {\n this.linearBBs[i].useDef.initializeGen(useDefContext);\n this.linearBBs[i].useDef.initializeKill(useDefContext);\n }\n var changed = true;\n\n while (changed) {\n changed = false;\n for (i = 0; i < bbLen; i++) {\n changed = this.linearBBs[i].useDef.updateTop() || changed;\n }\n }\n\n var top = this.entry.useDef.top;\n top.map((index) => {\n var ast = <Identifier>useDefContext.uses[<number>index];\n er.simpleError(ast, \"use of variable '\" + ast.actualText + \"' that is not definitely assigned\");\n });\n }\n\n public print(outfile: ITextWriter) {\n var index = 0;\n var node = (bb: BasicBlock) => {\n if (bb.index < 0) {\n bb.index = index++;\n }\n if (bb == this.exit) {\n outfile.WriteLine(\"Exit block with index \" + bb.index);\n }\n else {\n outfile.WriteLine(\"Basic block with index \" + bb.index);\n this.printBlockContent(bb, outfile);\n }\n }\n\n function preEdges() {\n outfile.Write(\" Branches to \");\n }\n\n function postEdges() {\n outfile.WriteLine(\"\");\n }\n\n function edge(node1: BasicBlock, node2: BasicBlock) {\n if (node2.index < 0) {\n node2.index = index++;\n }\n outfile.Write(node2.index + \" \");\n }\n\n this.bfs(node, edge, preEdges, postEdges);\n if (this.unreachable != null) {\n for (var i = 0, len = this.unreachable.length; i < len; i++) {\n outfile.WriteLine(\"Unreachable basic block ...\");\n this.printAST(this.unreachable[i], outfile);\n }\n }\n }\n\n public pushStatement(stmt: Statement, continueBB: BasicBlock, breakBB: BasicBlock) {\n this.statementStack.push({ stmt: stmt, continueBB: continueBB, breakBB: breakBB });\n }\n\n public popStatement() { return this.statementStack.pop(); }\n\n public returnStmt() {\n // TODO: make successor finally block if return stmt inside of try/finally \n this.current.addSuccessor(this.exit);\n this.setUnreachable();\n }\n\n public setUnreachable() {\n this.current = null;\n this.noContinuation = true;\n }\n\n public addUnreachable(ast: AST) {\n if (this.unreachable === null) {\n this.unreachable = new AST[];\n }\n this.unreachable[this.unreachable.length] = ast;\n }\n\n public unconditionalBranch(target: AST, isContinue: bool) {\n var targetBB = null;\n for (var i = 0, len = this.statementStack.length; i < len; i++) {\n var targetInfo = this.statementStack[i];\n if (targetInfo.stmt == target) {\n if (isContinue) {\n targetBB = targetInfo.continueBB;\n }\n else {\n targetBB = targetInfo.breakBB;\n }\n break;\n }\n }\n if (targetBB) {\n this.current.addSuccessor(targetBB);\n }\n this.setUnreachable();\n }\n\n public addContent(ast: AST): void {\n if (this.current) {\n this.current.content.append(ast);\n }\n }\n }\n\n export interface IResolutionData {\n actuals: Type[];\n exactCandidates: Signature[];\n conversionCandidates: Signature[];\n id: number;\n }\n\n export class ResolutionDataCache {\n public cacheSize = 16;\n public rdCache: IResolutionData[] = [];\n public nextUp: number = 0;\n\n constructor () {\n for (var i = 0; i < this.cacheSize; i++) {\n this.rdCache[i] = {\n actuals: new Type[],\n exactCandidates: new Signature[],\n conversionCandidates: new Signature[],\n id: i\n };\n }\n }\n\n public getResolutionData(): IResolutionData {\n var rd: IResolutionData = null;\n\n if (this.nextUp < this.cacheSize) {\n rd = this.rdCache[this.nextUp];\n }\n\n if (rd == null) {\n this.cacheSize++;\n rd = {\n actuals: new Type[],\n exactCandidates: new Signature[],\n conversionCandidates: new Signature[],\n id: this.cacheSize\n };\n this.rdCache[this.cacheSize] = rd;\n }\n\n // cache operates as a stack - RD is always served up in-order\n this.nextUp++;\n\n return rd;\n }\n\n public returnResolutionData(rd: IResolutionData) {\n // Pop to save on array allocations, which are a bottleneck\n // REVIEW: On some VMs, Array.pop doesn't always pop the last value in the array\n rd.actuals.length = 0;\n rd.exactCandidates.length = 0;\n rd.conversionCandidates.length = 0;\n\n this.nextUp = rd.id;\n }\n }\n\n export class TypeFlow {\n public scope: SymbolScope;\n public globalScope: SymbolScope;\n\n public thisType: Type;\n public thisFnc: FuncDecl = null;\n public thisClassNode: TypeDeclaration = null;\n public enclosingFncIsMethod = false;\n\n // REVIEW: Prune in favor of typechecker fields\n public doubleType: Type;\n public booleanType: Type;\n public stringType: Type;\n public anyType: Type;\n public regexType: Type;\n public nullType: Type;\n public voidType: Type;\n public arrayAnyType: Type;\n\n public arrayInterfaceType: Type = null;\n public stringInterfaceType: Type = null;\n public objectInterfaceType: Type = null;\n public functionInterfaceType: Type = null;\n public numberInterfaceType: Type = null;\n public booleanInterfaceType: Type = null;\n public iargumentsInterfaceType: Type = null;\n\n public currentScript: Script = null;\n\n public inImportTypeCheck = false;\n public inTypeRefTypeCheck = false;\n public inArrayElementTypeCheck = false;\n public resolutionDataCache = new ResolutionDataCache();\n public nestingLevel = 0;\n public inSuperCall = false;\n\n constructor (public logger: ILogger, public initScope: SymbolScope, public parser: Parser,\n public checker: TypeChecker) {\n this.checker.typeFlow = this;\n this.scope = this.initScope;\n this.globalScope = this.initScope;\n this.doubleType = this.checker.numberType;\n this.booleanType = this.checker.booleanType;\n this.stringType = this.checker.stringType;\n this.anyType = this.checker.anyType;\n this.regexType = this.anyType;\n this.nullType = this.checker.nullType;\n this.voidType = this.checker.voidType;\n this.arrayAnyType = this.checker.makeArrayType(this.anyType);\n }\n\n public initLibs() {\n var arraySym = this.globalScope.find(\"Array\", false, true);\n if (arraySym && (arraySym.kind() == SymbolKind.Type)) {\n this.arrayInterfaceType = (<TypeSymbol>arraySym).type;\n }\n var stringSym = this.globalScope.find(\"String\", false, true);\n if (stringSym && (stringSym.kind() == SymbolKind.Type)) {\n this.stringInterfaceType = (<TypeSymbol>stringSym).type;\n }\n var objectSym = this.globalScope.find(\"Object\", false, true);\n if (objectSym && (objectSym.kind() == SymbolKind.Type)) {\n this.objectInterfaceType = (<TypeSymbol>objectSym).type;\n }\n var fnSym = this.globalScope.find(\"Function\", false, true);\n if (fnSym && (fnSym.kind() == SymbolKind.Type)) {\n this.functionInterfaceType = (<TypeSymbol>fnSym).type;\n }\n var numberSym = this.globalScope.find(\"Number\", false, true);\n if (numberSym && (numberSym.kind() == SymbolKind.Type)) {\n this.numberInterfaceType = (<TypeSymbol>numberSym).type;\n }\n var booleanSym = this.globalScope.find(\"Boolean\", false, true);\n if (booleanSym && (booleanSym.kind() == SymbolKind.Type)) {\n this.booleanInterfaceType = (<TypeSymbol>booleanSym).type;\n }\n var regexSym = this.globalScope.find(\"RegExp\", false, true);\n if (regexSym && (regexSym.kind() == SymbolKind.Type)) {\n this.regexType = (<TypeSymbol>regexSym).type;\n }\n }\n\n public cast(ast: AST, type: Type): AST {\n return this.castWithCoercion(ast, type, true, false);\n }\n\n public castWithCoercion(ast: AST, type: Type, applyCoercion: bool, typeAssertion: bool): AST {\n var comparisonInfo = new TypeComparisonInfo();\n if (this.checker.sourceIsAssignableToTarget(ast.type, type, comparisonInfo) || (typeAssertion && this.checker.sourceIsAssignableToTarget(type, ast.type, comparisonInfo))) {\n if (applyCoercion) {\n if (type == null) {\n ast.type = this.anyType;\n }\n else if (type.isClass()) {\n ast.type = type.instanceType;\n }\n else {\n ast.type = type;\n }\n }\n return ast;\n }\n else {\n this.checker.errorReporter.incompatibleTypes(ast, ast.type, type, null, this.scope, comparisonInfo);\n return ast;\n }\n }\n\n public inScopeTypeCheck(ast: AST, enclosingScope: SymbolScope): AST {\n var prevScope = this.scope;\n this.scope = enclosingScope;\n var svThisFnc = this.thisFnc;\n var svThisType = this.thisType;\n var svThisClassNode = this.thisClassNode;\n var svCurrentModDecl = this.checker.currentModDecl;\n var prevMethodStatus = this.enclosingFncIsMethod;\n var container = this.scope.container;\n var fnc: FuncDecl = null;\n while (container) {\n if (container.kind() == SymbolKind.Type) {\n var typeSym = <TypeSymbol>container;\n var type = typeSym.type;\n if (type.call) {\n if (fnc == null) {\n // use innermost function\n this.enclosingFncIsMethod = typeSym.isMethod;\n fnc = <FuncDecl>container.declAST;\n }\n }\n if (type.isClass()) {\n this.thisType = type.instanceType;\n if (typeSym.declAST &&\n (typeSym.declAST.nodeType == NodeType.ClassDeclaration)) {\n this.thisClassNode = <TypeDeclaration>typeSym.declAST;\n }\n // use innermost class\n break;\n }\n if (type.isModuleType()) {\n this.checker.currentModDecl = <ModuleDeclaration>typeSym.declAST;\n // use innermost module\n break;\n }\n }\n container = container.container;\n }\n this.thisFnc = fnc;\n\n var updated = this.typeCheck(ast);\n\n this.thisFnc = svThisFnc;\n this.thisType = svThisType;\n this.thisClassNode = svThisClassNode;\n this.checker.currentModDecl = svCurrentModDecl;\n this.enclosingFncIsMethod = prevMethodStatus;\n this.scope = prevScope;\n return updated;\n }\n\n public typeCheck(ast: AST): AST {\n if (ast) {\n return ast.typeCheck(this);\n }\n else {\n return null;\n }\n }\n\n public inScopeTypeCheckDecl(ast: AST) {\n if (ast.nodeType == NodeType.VarDecl || ast.nodeType == NodeType.ArgDecl) {\n this.inScopeTypeCheckBoundDecl(<BoundDecl>ast);\n }\n else if (ast.nodeType == NodeType.FuncDecl) {\n\n var funcDecl = <FuncDecl>ast;\n\n if (funcDecl.isAccessor()) {\n this.typeCheckFunction(funcDecl);\n }\n }\n }\n\n public inScopeTypeCheckBoundDecl(varDecl: BoundDecl) {\n var sym = varDecl.sym;\n var svThisFnc = this.thisFnc;\n var svThisType = this.thisType;\n var prevMethodStatus = this.enclosingFncIsMethod;\n var prevLocationInfo = this.checker.locationInfo;\n if (sym && sym.container) {\n var instanceScope = hasFlag(varDecl.varFlags, VarFlags.ClassConstructorProperty) ? sym.container.getType().constructorScope : sym.container.instanceScope();\n if (hasFlag(varDecl.varFlags, VarFlags.Property) && sym.container.declAST.nodeType == NodeType.FuncDecl) {\n this.thisFnc = <FuncDecl>sym.container.declAST;\n }\n if (instanceScope) {\n var prevScope = this.scope;\n this.scope = instanceScope;\n var container = sym.container;\n var svCurrentModDecl = this.checker.currentModDecl;\n if (this.checker.units &&\n (sym.unitIndex >= 0) &&\n (sym.unitIndex < this.checker.units.length)) {\n this.checker.locationInfo = this.checker.units[sym.unitIndex];\n }\n else {\n this.checker.locationInfo = unknownLocationInfo;\n }\n // REVIEW: container linkage for function expressions\n while (container) {\n if (container.kind() == SymbolKind.Type) {\n var typeSym = <TypeSymbol>container;\n var type = typeSym.type;\n if (type.call) {\n this.enclosingFncIsMethod = typeSym.isMethod;\n }\n if (type.isClass()) {\n this.thisType = type.instanceType;\n }\n if (type.isModuleType()) {\n this.checker.currentModDecl = <ModuleDeclaration>container.declAST;\n break;\n }\n }\n container = container.container;\n }\n\n this.typeCheckBoundDecl(varDecl);\n this.checker.currentModDecl = svCurrentModDecl;\n this.scope = prevScope;\n }\n }\n this.thisFnc = svThisFnc;\n this.thisType = svThisType;\n this.checker.locationInfo = prevLocationInfo;\n this.enclosingFncIsMethod = prevMethodStatus;\n }\n\n public resolveBoundDecl(varDecl: BoundDecl) {\n if (varDecl.typeExpr) {\n if (varDecl.typeExpr.type == null ||\n (varDecl.typeExpr.type && varDecl.typeExpr.type == this.anyType && this.scope) ||\n varDecl.typeExpr.type.symbol == null ||\n !this.checker.typeStatusIsFinished(varDecl.typeExpr.type.symbol.typeCheckStatus)) {\n this.typeCheck(varDecl.typeExpr);\n }\n varDecl.type = varDecl.typeExpr.type;\n if (varDecl.sym) {\n varDecl.sym.setType(varDecl.type);\n }\n }\n else if (varDecl.init == null) {\n if (this.checker.styleSettings.implicitAny) {\n this.checker.errorReporter.styleError(varDecl, \"type implicitly set to 'any'\");\n }\n varDecl.type = this.anyType;\n if (varDecl.sym) {\n if (varDecl.sym.isType()) {\n var tsym = <TypeSymbol>varDecl.sym;\n if (tsym.isMethod) {\n this.checker.errorReporter.simpleError(varDecl, \"Cannot bind method group to variable. (Did you mean to use 'declare function' instead of 'declare var'?)\");\n return;\n }\n else {\n this.checker.errorReporter.simpleError(varDecl, \"Cannot bind type to variable\");\n return;\n }\n }\n varDecl.sym.setType(varDecl.type);\n }\n }\n }\n\n public typeCheckBoundDecl(varDecl: BoundDecl): VarDecl {\n // symbol has already been added to the scope\n var infSym = <InferenceSymbol>varDecl.sym;\n if (infSym == null) {\n if (varDecl.init) {\n varDecl.init = this.typeCheck(varDecl.init);\n varDecl.type = this.checker.widenType(varDecl.init.type);\n }\n else {\n if (this.checker.styleSettings.implicitAny) {\n this.checker.errorReporter.styleError(varDecl, \"type implicitly set to 'any'\");\n }\n varDecl.type = this.anyType;\n }\n }\n else {\n if (infSym.typeCheckStatus == TypeCheckStatus.Started) {\n if (this.checker.styleSettings.implicitAny) {\n this.checker.errorReporter.styleError(varDecl, \"type implicitly set to 'any'\");\n }\n varDecl.type = this.anyType;\n infSym.setType(this.anyType);\n }\n else if (infSym.typeCheckStatus == TypeCheckStatus.NotStarted) {\n infSym.typeCheckStatus = TypeCheckStatus.Started;\n this.checker.addStartedPTO(infSym);\n var resolved = false;\n if (varDecl.type == null) {\n // propagate declared type\n if (varDecl.typeExpr) {\n this.resolveBoundDecl(varDecl);\n resolved = true;\n varDecl.type = varDecl.typeExpr.type;\n infSym.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n }\n }\n\n if (varDecl.init) {\n // if the bound decl is a function-local static, we need to set the\n // encapsulating scope to the function's member scope\n var isLocalStatic = hasFlag(varDecl.varFlags, VarFlags.LocalStatic);\n var prevScope = this.scope;\n var applyTargetType = !varDecl.init.isParenthesized;\n if (isLocalStatic) {\n this.scope = varDecl.sym.container.getType().memberScope;\n }\n\n // Mark Lambda expressions with IsPropertyBound flag\n if (hasFlag(varDecl.varFlags, VarFlags.Property) && this.thisClassNode) {\n getAstWalkerFactory().walk(varDecl.init, (ast: AST, parent: AST, walker: IAstWalker) => {\n if (ast && ast.nodeType == NodeType.FuncDecl) {\n if (hasFlag((<FuncDecl>ast).fncFlags, FncFlags.IsFatArrowFunction)) {\n // Found a Lambda, mark it\n (<FuncDecl>ast).fncFlags |= FncFlags.IsPropertyBound;\n }\n // Only mark the top level functions\n walker.options.goChildren = false;\n }\n return ast;\n });\n }\n\n this.checker.typeCheckWithContextualType(varDecl.type, this.checker.inProvisionalTypecheckMode(), applyTargetType, varDecl.init);\n\n this.scope = prevScope;\n if (varDecl.type) {\n // If the cast is to a target type, in the case of a funcdecl,\n // we may overwrite the init's type with one generated from a signature.\n // In that case, we need to preserve the contained scope of the actual decl\n var preserveScope = false;\n var preservedContainedScope = null;\n\n if (varDecl.init.type) {\n preservedContainedScope = varDecl.init.type.containedScope;\n preserveScope = true;\n if (varDecl.init.type == this.voidType) {\n this.checker.errorReporter.simpleError(varDecl, \"Cannot assign type 'void' to variable '\" + varDecl.id.actualText + \"'\");\n }\n }\n\n varDecl.init = this.castWithCoercion(varDecl.init, varDecl.type, applyTargetType && !this.checker.inProvisionalTypecheckMode(), false);\n\n if (preserveScope && varDecl.init.type.containedScope == null) {\n varDecl.init.type.containedScope = preservedContainedScope;\n }\n }\n else {\n varDecl.type = this.checker.widenType(varDecl.init.type);\n if (varDecl.type == this.voidType) {\n this.checker.errorReporter.simpleError(varDecl, \"Cannot assign type 'void' to variable '\" + varDecl.id.actualText + \"'\");\n varDecl.type = this.anyType;\n }\n }\n infSym.setType(varDecl.type);\n }\n else {\n if (!resolved) {\n this.resolveBoundDecl(varDecl);\n }\n }\n infSym.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n }\n else if (this.checker.typeStatusIsFinished(infSym.typeCheckStatus) &&\n (infSym.declAST != varDecl)) {\n if (varDecl.init) {\n varDecl.init = this.typeCheck(varDecl.init);\n varDecl.type = infSym.getType();\n varDecl.init = this.cast(varDecl.init, varDecl.type);\n }\n }\n }\n if (varDecl.id && varDecl.sym) {\n varDecl.id.sym = varDecl.sym;\n }\n\n // Check if variable satisfies type privacy\n if (varDecl.sym && varDecl.sym.container) {\n this.checkTypePrivacy(varDecl.sym.getType(), varDecl.sym, (typeName: string, isModuleName: bool) => this.varPrivacyErrorReporter(varDecl, typeName, isModuleName));\n }\n return <VarDecl>varDecl;\n }\n\n private varPrivacyErrorReporter(varDecl: BoundDecl, typeName: string, isModuleName: bool) {\n var typestring = \"\";\n if (isModuleName) {\n var quotestring = \"\";\n if (!isQuoted(typeName)) {\n quotestring = \"'\";\n }\n typestring = \" is using inaccessible module \" + quotestring + typeName + quotestring;\n } else {\n typestring = \" has or is using private type '\" + typeName + \"'\";\n }\n\n if (hasFlag(varDecl.varFlags, VarFlags.Public)) {\n if (varDecl.sym.container.declAST.nodeType == NodeType.InterfaceDeclaration) {\n this.checker.errorReporter.simpleError(varDecl, \"property '\" + varDecl.sym.name + \"' of exported interface\" + typestring);\n } else {\n this.checker.errorReporter.simpleError(varDecl, \"public member '\" + varDecl.sym.name + \"' of exported class\" + typestring);\n }\n } else {\n this.checker.errorReporter.simpleError(varDecl, \"exported variable '\" + varDecl.sym.name + \"'\" + typestring);\n }\n }\n\n public typeCheckSuper(ast: AST): AST {\n if (this.thisType && (this.enclosingFncIsMethod && !this.thisFnc.isStatic()) && this.thisType.baseClass()) {\n ast.type = this.thisType.baseClass();\n }\n else {\n // redirect 'super' used within lambdas\n if (!this.enclosingFncIsMethod &&\n this.thisType && this.thisType.baseClass() &&\n this.thisFnc && hasFlag(this.thisFnc.fncFlags, FncFlags.IsFatArrowFunction)) {\n // Find the closest non lambda function\n var enclosingFnc = this.thisFnc.enclosingFnc;\n while (hasFlag(enclosingFnc.fncFlags, FncFlags.IsFatArrowFunction)) {\n enclosingFnc = enclosingFnc.enclosingFnc;\n }\n\n // If the lambda is enclosed is a valid member, use the base type\n if (enclosingFnc && (enclosingFnc.isMethod() || enclosingFnc.isConstructor) && !enclosingFnc.isStatic()) {\n ast.type = this.thisType.baseClass();\n enclosingFnc.setHasSuperReferenceInFatArrowFunction();\n return ast;\n }\n }\n\n ast.type = this.anyType;\n this.checker.errorReporter.invalidSuperReference(ast);\n }\n return ast;\n }\n\n public typeCheckThis(ast: AST): AST {\n ast.type = this.anyType;\n var illegalThisRef = false;\n if (this.thisFnc == null) {\n // 'this' in class bodies should bind to 'any'\n if (this.thisType) {\n if (this.thisClassNode && this.thisClassNode.nodeType == NodeType.ClassDeclaration) {\n illegalThisRef = true;\n }\n else {\n ast.type = this.thisType;\n }\n }\n else if (this.checker.currentModDecl) {\n this.checker.errorReporter.simpleError(ast, \"'this' may not be referenced within module bodies\");\n }\n }\n else {\n if (this.thisClassNode && (hasFlag(this.thisFnc.fncFlags, FncFlags.IsPropertyBound) || (this.inSuperCall && hasFlag((<ClassDeclaration>this.thisClassNode).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor)))) {\n illegalThisRef = true;\n }\n if (this.thisFnc.isMethod() || this.thisFnc.isConstructor || this.thisFnc.isTargetTypedAsMethod) {\n if (this.thisType && !(this.thisFnc.fncFlags & FncFlags.Static)) {\n ast.type = this.thisType;\n }\n }\n }\n\n // redirect 'this' used within lambdas\n if (!this.enclosingFncIsMethod &&\n this.thisFnc &&\n hasFlag(this.thisFnc.fncFlags, FncFlags.IsFatArrowFunction)) {\n\n // if the enclosing function was bound to a property,\n // checkInitSelf would not have been able to mark the \n // function for a self init\n if (this.thisFnc.boundToProperty) {\n var container = this.thisFnc.boundToProperty.sym.container;\n if (container.declAST.nodeType == NodeType.FuncDecl) {\n (<FuncDecl>container.declAST).setHasSelfReference();\n }\n }\n else {\n var encFnc = this.thisFnc.enclosingFnc;\n var firstEncFnc = encFnc;\n\n while (encFnc) {\n if (this.thisClassNode && hasFlag(encFnc.fncFlags, FncFlags.IsPropertyBound)) {\n illegalThisRef = true;\n }\n\n if (!hasFlag(encFnc.fncFlags, FncFlags.IsFatArrowFunction) || encFnc.hasSelfReference()) {\n encFnc.setHasSelfReference();\n break;\n }\n\n encFnc = encFnc.enclosingFnc;\n }\n\n if (!encFnc && firstEncFnc) {\n encFnc = firstEncFnc;\n encFnc.setHasSelfReference();\n }\n else if (!encFnc) { // the lambda is bound at the top-level...\n if (this.thisClassNode) {\n (<ClassDeclaration>this.thisClassNode).varFlags |= VarFlags.MustCaptureThis;\n }\n else if (this.checker.currentModDecl) {\n this.checker.currentModDecl.modFlags |= ModuleFlags.MustCaptureThis;\n }\n else {\n this.checker.mustCaptureGlobalThis = true;\n }\n }\n\n if (encFnc && (encFnc.isMethod() || encFnc.isConstructor) && this.thisType && !hasFlag(encFnc.fncFlags, FncFlags.Static)) {\n ast.type = this.thisType;\n }\n }\n }\n\n if (illegalThisRef) {\n this.checker.errorReporter.simpleError(ast, \"Keyword 'this' cannot be referenced in initializers in a class body, or in super constructor calls\");\n }\n return ast;\n }\n\n public setTypeFromSymbol(ast: AST, symbol: Symbol): void {\n if (symbol.isVariable()) {\n if (symbol.isInferenceSymbol()) {\n var infSym = <InferenceSymbol>symbol;\n if (infSym.declAST &&\n !this.checker.typeStatusIsFinished(infSym.typeCheckStatus)) {\n this.inScopeTypeCheckDecl(infSym.declAST);\n }\n if (!this.checker.styleSettings.innerScopeDeclEscape) {\n if (infSym.declAST && (infSym.declAST.nodeType == NodeType.VarDecl)) {\n if (this.nestingLevel < (<VarDecl>infSym.declAST).nestingLevel) {\n this.checker.errorReporter.styleError(ast, \"Illegal reference to a variable defined in more nested scope\");\n }\n }\n }\n }\n ast.type = symbol.getType();\n if (!symbol.writeable()) {\n ast.flags = ast.flags & (~(ASTFlags.Writeable));\n }\n }\n else if (symbol.isType()) {\n ast.type = symbol.getType();\n ast.flags = ast.flags & (~(ASTFlags.Writeable));\n }\n else {\n ast.type = this.anyType;\n this.checker.errorReporter.symbolDoesNotReferToAValue(ast, symbol.name);\n }\n }\n\n public typeCheckName(ast: AST): AST {\n var identifier = <Identifier>ast;\n\n if (this.checker.inWith) {\n identifier.type = this.anyType;\n }\n else {\n var typespace = this.inTypeRefTypeCheck;\n var idText = identifier.text;\n var originalIdText = idText;\n var isDynamicModuleName = isQuoted(identifier.text);\n\n var symbol = this.scope.find(idText, false, typespace);\n\n if (symbol == null && isDynamicModuleName) {\n symbol = this.checker.findSymbolForDynamicModule(idText, this.currentScript.locationInfo.filename, (id) => this.scope.find(id, false, typespace));\n }\n\n if (!symbol) {\n if (!identifier.isMissing()) {\n this.checker.errorReporter.unresolvedSymbol(identifier, identifier.text);\n }\n identifier.type = this.anyType;\n }\n else {\n if (optimizeModuleCodeGen && symbol && symbol.isType()) {\n var symType = symbol.getType();\n // Once the type has been referenced outside of a type ref position, there's\n // no going back \n if (symType && (<TypeSymbol>symbol).aliasLink && (<TypeSymbol>symbol).onlyReferencedAsTypeRef) {\n\n var modDecl = <ModuleDeclaration>symType.symbol.declAST;\n if (modDecl && hasFlag(modDecl.modFlags, ModuleFlags.IsDynamic)) {\n (<TypeSymbol>symbol).onlyReferencedAsTypeRef = this.inTypeRefTypeCheck;\n }\n }\n }\n\n if (symbol.declAST &&\n symbol.declAST.nodeType == NodeType.FuncDecl &&\n !(<FuncDecl>symbol.declAST).returnTypeAnnotation &&\n (<FuncDecl>symbol.declAST).signature.typeCheckStatus == TypeCheckStatus.Started) {\n (<FuncDecl>symbol.declAST).type.symbol.flags |= SymbolFlags.RecursivelyReferenced;\n (<FuncDecl>symbol.declAST).signature.returnType.type = this.anyType;\n }\n\n this.setTypeFromSymbol(ast, symbol);\n identifier.sym = symbol;\n if (this.thisFnc) {\n if (this.thisFnc.type && symbol.container != this.thisFnc.type.symbol) {\n this.thisFnc.freeVariables[this.thisFnc.freeVariables.length] = symbol;\n }\n }\n }\n }\n return ast;\n }\n\n public typeCheckScript(script: Script): Script {\n this.checker.locationInfo = script.locationInfo;\n this.scope = this.checker.globalScope;\n\n // if it's a top-level module, the globals have already been added to the implicit\n // module decl\n if (!script.topLevelMod) {\n this.addLocalsFromScope(this.scope, this.checker.gloMod,\n script.vars, this.checker.globals, true);\n }\n\n this.currentScript = script;\n script.bod = <ASTList>this.typeCheck(script.bod);\n this.currentScript = null;\n return script;\n }\n\n public typeCheckBitNot(ast: AST): AST {\n var unex = <UnaryExpression>ast;\n unex.operand = this.typeCheck(unex.operand);\n unex.type = this.doubleType;\n return unex;\n }\n\n public typeCheckUnaryNumberOperator(ast: AST): AST {\n var unex = <UnaryExpression>ast;\n unex.operand = this.typeCheck(unex.operand);\n unex.type = this.doubleType;\n return ast;\n }\n\n public typeCheckLogNot(ast: AST): AST {\n var unex = <UnaryExpression>ast;\n unex.operand = this.typeCheck(unex.operand);\n unex.type = this.booleanType;\n return unex;\n }\n\n public astIsWriteable(ast: AST): bool {\n return hasFlag(ast.flags, ASTFlags.Writeable);\n }\n\n public typeCheckIncOrDec(ast: AST): AST {\n var unex = <UnaryExpression>ast;\n var lval = unex.operand;\n if (!this.astIsWriteable(unex)) {\n this.checker.errorReporter.valueCannotBeModified(unex);\n unex.type = this.doubleType;\n }\n else {\n unex = <UnaryExpression> this.typeCheckUnaryNumberOperator(ast);\n if (unex.operand.type != this.checker.numberType && unex.operand.type != this.checker.anyType && !(unex.operand.type.typeFlags & TypeFlags.IsEnum)) {\n this.checker.errorReporter.simpleError(ast, \"'++' and '--' may only be applied to operands of type 'number' or 'any'\");\n }\n }\n return unex;\n }\n\n public typeCheckBitwiseOperator(ast: AST, assignment: bool): AST {\n var binex = <BinaryExpression>ast;\n var resultType: Type = null;\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n var leftType = binex.operand1.type;\n var rightType = binex.operand2.type;\n\n if (assignment && (!this.astIsWriteable(binex))) {\n this.checker.errorReporter.valueCannotBeModified(binex);\n }\n\n if (this.checker.styleSettings.bitwise) {\n this.checker.errorReporter.styleError(ast, \"use of \" + nodeTypeTable[binex.nodeType]);\n }\n\n if (this.checker.sourceIsSubtypeOfTarget(leftType, this.doubleType) && (this.checker.sourceIsSubtypeOfTarget(rightType, this.doubleType))) {\n resultType = this.doubleType;\n }\n else if ((leftType == this.booleanType) &&\n (rightType == this.booleanType)) {\n resultType = this.booleanType;\n }\n else if (leftType == this.anyType) {\n if ((rightType == this.anyType) ||\n (rightType == this.doubleType) ||\n (rightType == this.booleanType)) {\n resultType = this.anyType;\n }\n }\n else if (rightType == this.anyType) {\n if ((leftType == this.anyType) ||\n (leftType == this.doubleType) ||\n (leftType == this.booleanType)) {\n resultType = this.anyType;\n }\n }\n if (resultType == null) {\n resultType = this.anyType;\n this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType,\n binex.printLabel(), this.scope);\n }\n binex.type = resultType;\n return binex;\n }\n\n public typeCheckArithmeticOperator(ast: AST, assignment: bool): AST {\n var binex = <BinaryExpression>ast;\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n var leftType = binex.operand1.type;\n var rightType = binex.operand2.type;\n\n if (assignment && (!this.astIsWriteable(binex.operand1))) {\n this.checker.errorReporter.valueCannotBeModified(binex);\n }\n\n if (this.checker.styleSettings.bitwise &&\n ((binex.nodeType == NodeType.And) ||\n (binex.nodeType == NodeType.Or) ||\n (binex.nodeType == NodeType.AsgAnd) ||\n (binex.nodeType == NodeType.AsgOr))) {\n this.checker.errorReporter.styleError(ast, \"use of \" + nodeTypeTable[binex.nodeType]);\n }\n\n if (leftType == null || rightType == null) {\n this.checker.errorReporter.simpleError(binex, \"Could not typecheck arithmetic operation. Possible recursive typecheck error?\");\n binex.type = this.anyType;\n return binex;\n }\n var nodeType = binex.nodeType;\n\n if (this.checker.isNullOrUndefinedType(leftType)) {\n leftType = rightType;\n }\n if (this.checker.isNullOrUndefinedType(rightType)) {\n rightType = leftType;\n }\n leftType = this.checker.widenType(leftType);\n rightType = this.checker.widenType(rightType);\n\n if (nodeType == NodeType.Add || nodeType == NodeType.AsgAdd) {\n\n if (leftType == this.checker.stringType || rightType == this.checker.stringType) {\n binex.type = this.checker.stringType;\n }\n else if (leftType == this.checker.numberType && rightType == this.checker.numberType) {\n binex.type = this.checker.numberType;\n }\n else if (this.checker.sourceIsSubtypeOfTarget(leftType, this.checker.numberType) && this.checker.sourceIsSubtypeOfTarget(rightType, this.checker.numberType)) {\n binex.type = this.checker.numberType;\n }\n else if (leftType == this.checker.anyType || rightType == this.checker.anyType) {\n binex.type = this.checker.anyType;\n }\n else {\n binex.type = this.anyType;\n this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType,\n binex.printLabel(), this.scope);\n }\n }\n else {\n if (leftType == this.checker.numberType && rightType == this.checker.numberType) {\n binex.type = this.checker.numberType;\n }\n else if (this.checker.sourceIsSubtypeOfTarget(leftType, this.checker.numberType) && this.checker.sourceIsSubtypeOfTarget(rightType, this.checker.numberType)) {\n binex.type = this.checker.numberType;\n }\n else if (leftType == this.checker.anyType || rightType == this.checker.anyType) {\n binex.type = this.checker.numberType;\n }\n else {\n binex.type = this.anyType;\n this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType,\n binex.printLabel(), this.scope);\n }\n }\n\n return binex;\n }\n\n public typeCheckDotOperator(ast: AST): AST {\n var binex = <BinaryExpression>ast;\n var leftIsFnc = false;\n binex.operand1 = this.typeCheck(binex.operand1);\n var leftType = binex.operand1.type;\n var leftScope: SymbolScope = null;\n // REVIEW: replace with get member scope\n if (leftType) {\n if (leftType == this.anyType) {\n binex.type = this.anyType;\n return binex;\n }\n else if (leftType == this.stringType) {\n if (this.stringInterfaceType) {\n leftScope = this.stringInterfaceType.memberScope;\n }\n else {\n binex.type = this.anyType;\n return binex;\n }\n }\n else if (leftType == this.doubleType) {\n if (this.numberInterfaceType) {\n leftScope = this.numberInterfaceType.memberScope;\n }\n else {\n binex.type = this.anyType;\n return binex;\n }\n }\n else if (leftType == this.booleanType) {\n if (this.booleanInterfaceType) {\n leftScope = this.booleanInterfaceType.memberScope;\n }\n else {\n binex.type = this.anyType;\n return binex;\n }\n }\n else if ((leftType.call || leftType.construct) && leftType.members == null) {\n if (this.functionInterfaceType) {\n leftScope = this.functionInterfaceType.memberScope;\n }\n else {\n binex.type = this.anyType;\n return binex;\n }\n }\n else if (leftType.elementType) {\n if (this.arrayInterfaceType) {\n var arrInstType = leftType.elementType.getArrayBase(this.arrayInterfaceType, this.checker);\n leftScope = arrInstType.memberScope;\n }\n else {\n binex.type = this.anyType;\n return binex;\n }\n }\n else {\n leftScope = leftType.memberScope;\n }\n }\n if (leftScope == null) {\n this.checker.errorReporter.expectedClassOrInterface(binex);\n binex.type = this.anyType;\n }\n else {\n var propertyName = <Identifier>binex.operand2;\n var lhsIsEnclosingType = (this.thisClassNode && binex.operand1.type == this.thisClassNode.type.instanceType) || this.inTypeRefTypeCheck;\n var symbol = leftScope.find(propertyName.text, !lhsIsEnclosingType, this.inTypeRefTypeCheck); // only search the public members, unless the rhs is a 'this' pointer\n\n // If the symbol wasn't found, delegate to the appropriate 'virtual' parent type\n if (!symbol) {\n if (this.objectInterfaceType && leftType) {\n // check 'Object' for the symbol\n if (leftType.isReferenceType()) {\n symbol = this.objectInterfaceType.memberScope.find(propertyName.text, false, this.inTypeRefTypeCheck);\n }\n if (!symbol) {\n // check 'Function', if appropriate\n if (this.functionInterfaceType && (leftType.call || leftType.construct)) {\n symbol = this.functionInterfaceType.memberScope.find(propertyName.text, false, this.inTypeRefTypeCheck);\n }\n }\n }\n }\n\n if (!symbol || (!symbol.visible(leftScope, this.checker))) {\n binex.type = this.anyType;\n\n if (symbol == null) {\n this.checker.errorReporter.simpleError(propertyName, \"The property '\" + propertyName.actualText + \"' does not exist on value of type '\" + leftType.getScopedTypeName(this.scope) + \"'\");\n }\n else if (!this.inTypeRefTypeCheck) { // if it's a dotted type reference, we'll catch the visibility error during binding\n this.checker.errorReporter.simpleError(binex, \"The property '\" + propertyName.actualText + \" on type '\" + leftType.getScopedTypeName(this.scope) + \"' is not visible\");\n }\n }\n else {\n if (symbol.isVariable()) {\n if (symbol.isInferenceSymbol()) {\n var infSym = <InferenceSymbol>symbol;\n if (infSym.declAST && !this.checker.typeStatusIsFinished(infSym.typeCheckStatus)) {\n this.inScopeTypeCheckDecl(infSym.declAST);\n }\n }\n }\n propertyName.sym = symbol;\n binex.type = symbol.getType();\n }\n }\n if (binex.type == null) {\n binex.type = this.anyType;\n }\n\n return binex;\n }\n\n public typeCheckBooleanOperator(ast: AST): AST {\n var binex = <BinaryExpression>ast;\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n var leftType = binex.operand1.type;\n var rightType = binex.operand2.type;\n if ((!(this.checker.sourceIsAssignableToTarget(leftType, rightType))) &&\n (!(this.checker.sourceIsAssignableToTarget(rightType, leftType)))) {\n this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType, binex.printLabel(), this.scope);\n }\n binex.type = this.booleanType;\n return binex;\n }\n\n public typeCheckAsgOperator(ast: AST): AST {\n var binex = <BinaryExpression>ast;\n var applyTargetType = !binex.operand2.isParenthesized;\n binex.operand1 = this.typeCheck(binex.operand1);\n\n this.checker.typeCheckWithContextualType(binex.operand1.type, this.checker.inProvisionalTypecheckMode(), applyTargetType, binex.operand2);\n\n var leftType = binex.operand1.type;\n var rightType = binex.operand2.type;\n\n if (!(this.astIsWriteable(binex.operand1))) {\n this.checker.errorReporter.valueCannotBeModified(binex);\n }\n if (binex.operand1.nodeType == NodeType.Call) {\n var callEx = <CallExpression>binex.operand1;\n }\n var preserveScope = false;\n var preservedContainedScope = null;\n if (binex.operand2.type) {\n preservedContainedScope = binex.operand2.type.containedScope;\n preserveScope = true;\n }\n // Do not re-write the AST in provisional typecheck mode\n binex.operand2 = this.castWithCoercion(binex.operand2, leftType, applyTargetType && !this.checker.inProvisionalTypecheckMode(), false);\n if (preserveScope && binex.operand2.type.containedScope == null) {\n binex.operand2.type.containedScope = preservedContainedScope;\n }\n binex.type = rightType;\n return binex;\n }\n\n public typeCheckIndex(ast: AST): AST {\n var binex = <BinaryExpression>ast;\n binex.operand1 = this.typeCheck(binex.operand1); // ObjExpr\n binex.operand2 = this.typeCheck(binex.operand2); // IndexExpr\n\n if (!this.checker.styleSettings.literalSubscript) {\n if (binex.operand2.nodeType == NodeType.QString) {\n this.checker.errorReporter.styleError(ast, \"use literal subscript ('.') notation instead)\");\n }\n }\n\n var objExprType = binex.operand1.type;\n var indexExprType = binex.operand2.type;\n\n if (objExprType.elementType) { // arrays\n if (indexExprType == this.checker.anyType || indexExprType == this.checker.numberType || hasFlag(indexExprType.typeFlags, TypeFlags.IsEnum)) {\n binex.type = objExprType.elementType;\n }\n else if (indexExprType == this.checker.stringType) {\n binex.type = this.checker.anyType;\n }\n else {\n this.checker.errorReporter.simpleError(binex, \"Illegal property access\");\n binex.type = this.checker.anyType;\n }\n }\n else if (objExprType.index) { // types with index sigs\n\n if (indexExprType == this.checker.anyType ||\n !((objExprType.index.flags & SignatureFlags.IsStringIndexer) || (objExprType.index.flags & SignatureFlags.IsNumberIndexer)) || // REVIEW: unvalidated type expression\n ((objExprType.index.flags & SignatureFlags.IsStringIndexer) && indexExprType == this.checker.stringType) ||\n ((objExprType.index.flags & SignatureFlags.IsNumberIndexer) && (indexExprType == this.checker.numberType || hasFlag(indexExprType.typeFlags, TypeFlags.IsEnum)))) {\n var sig = this.resolveOverload(ast, objExprType.index);\n if (sig) {\n binex.type = sig.returnType.type;//objExprType.index.signatures[0].returnType.type;\n }\n else {\n binex.type = this.checker.anyType;\n }\n }\n else if (indexExprType == this.checker.stringType) {\n binex.type = this.checker.anyType;\n }\n else {\n this.checker.errorReporter.simpleError(binex, \"Illegal property access\");\n binex.type = this.checker.anyType;\n }\n }\n else if ((objExprType == this.checker.anyType ||\n objExprType == this.checker.stringType ||\n objExprType == this.checker.numberType ||\n objExprType == this.checker.booleanType ||\n objExprType.isReferenceType()) &&\n (indexExprType == this.checker.anyType ||\n indexExprType == this.checker.stringType ||\n (indexExprType == this.checker.numberType || hasFlag(indexExprType.typeFlags, TypeFlags.IsEnum)))) { // REVIEW: Do we want to allow indexes of type 'number'?\n binex.type = this.checker.anyType;\n }\n else {\n this.checker.errorReporter.simpleError(binex, \"Illegal property access\");\n binex.type = this.checker.anyType;\n }\n\n return binex;\n }\n\n public typeCheckInOperator(binex: BinaryExpression): BinaryExpression {\n binex.operand1 = this.cast(this.typeCheck(binex.operand1), this.stringType);\n binex.operand2 = this.typeCheck(binex.operand2);\n\n if (!((binex.operand1.type == this.checker.anyType || binex.operand1.type == this.checker.stringType) &&\n (binex.operand2.type == this.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand2.type, this.objectInterfaceType)))) {\n this.checker.errorReporter.simpleError(binex, \"The in operator requires the left operand to be of type Any or the String primitive type, and the right operand to be of type Any or an object type\");\n }\n\n binex.type = this.booleanType;\n return binex;\n }\n\n public typeCheckShift(binex: BinaryExpression, assignment: bool): BinaryExpression {\n binex.operand1 = this.cast(this.typeCheck(binex.operand1), this.doubleType);\n binex.operand2 = this.cast(this.typeCheck(binex.operand2), this.doubleType);\n if (assignment && (!(this.astIsWriteable(binex.operand1)))) {\n this.checker.errorReporter.valueCannotBeModified(binex);\n }\n binex.type = this.doubleType;\n return binex;\n }\n\n public typeCheckQMark(trinex: ConditionalExpression): ConditionalExpression {\n trinex.operand1 = this.typeCheck(trinex.operand1);\n trinex.operand2 = this.typeCheck(trinex.operand2);\n trinex.operand3 = this.typeCheck(trinex.operand3);\n var leftType = trinex.operand2.type;\n var rightType = trinex.operand3.type;\n\n if (leftType == rightType) {\n trinex.type = leftType;\n }\n else {\n if (this.checker.sourceIsSubtypeOfTarget(leftType, rightType)) {\n trinex.type = rightType;\n }\n else if (this.checker.sourceIsSubtypeOfTarget(rightType, leftType)) {\n trinex.type = leftType;\n }\n else {\n trinex.type = this.anyType;\n this.checker.errorReporter.incompatibleTypes(trinex, leftType, rightType, trinex.printLabel(), this.scope);\n }\n }\n\n return trinex;\n }\n\n public addFormals(container: Symbol, signature: Signature,\n table: IHashTable) {\n var len = signature.parameters.length;\n for (var i = 0; i < len; i++) {\n var symbol = <ParameterSymbol>signature.parameters[i];\n symbol.container = container;\n table.add(symbol.name, symbol);\n }\n }\n\n // REVIEW: We use isModContainer instead of container.getType().isModuleType because container.type may be null at this\n // juncture\n public addLocalsFromScope(scope: SymbolScope, container: Symbol, vars: ASTList, table: IHashTable, isModContainer: bool) {\n var len = vars.members.length;\n var hasArgsDef = false;\n for (var i = 0; i < len; i++) {\n var local = <VarDecl>vars.members[i];\n if (((local.sym == null) || (local.sym.kind() != SymbolKind.Field))) {\n var result: Symbol = null;\n if ((result = table.lookup(local.id.text)) == null) {\n var localVar: ValueLocation = new ValueLocation();\n localVar.typeLink = new TypeLink();\n var varSym = null;\n\n if (hasFlag(local.varFlags, VarFlags.Static)) {\n local.varFlags |= VarFlags.LocalStatic;\n varSym = new FieldSymbol(local.id.text, local.minChar,\n this.checker.locationInfo.unitIndex,\n true, localVar);\n }\n else {\n varSym = new VariableSymbol(local.id.text, local.minChar,\n this.checker.locationInfo.unitIndex,\n localVar);\n }\n varSym.transferVarFlags(local.varFlags);\n localVar.symbol = varSym;\n varSym.declAST = local;\n localVar.typeLink.ast = local.typeExpr;\n this.checker.resolveTypeLink(scope, localVar.typeLink, false);\n if ((local.type == null) && (local.init == null)) {\n local.type = this.anyType;\n }\n localVar.typeLink.type = local.type;\n localVar.symbol.container = container;\n local.sym = localVar.symbol;\n table.add(local.id.text, varSym);\n if (local.id.text == \"arguments\") {\n hasArgsDef = true;\n }\n }\n else {\n local.type = result.getType();\n local.sym = result;\n }\n }\n }\n if (!isModContainer) {\n if (!hasArgsDef) {\n var argLoc = new ValueLocation();\n argLoc.typeLink = new TypeLink();\n var theArgSym = new VariableSymbol(\"arguments\", vars.minChar,\n this.checker.locationInfo.unitIndex,\n argLoc);\n\n // if the user is using a custom lib.d.ts where IArguments has not been defined\n // (or they're compiling with the --nolib option), use 'any' as the argument type\n if (!this.iargumentsInterfaceType) {\n var argumentsSym = scope.find(\"IArguments\", false, true);\n\n if (argumentsSym) {\n argumentsSym.flags |= SymbolFlags.CompilerGenerated;\n this.iargumentsInterfaceType = argumentsSym.getType();\n }\n else {\n this.iargumentsInterfaceType = this.anyType;\n }\n }\n argLoc.typeLink.type = this.iargumentsInterfaceType;\n table.add(\"arguments\", theArgSym);\n }\n }\n }\n\n // REVIEW: isClass param may now be redundant\n public addConstructorLocalArgs(container: Symbol, args: ASTList, table: IHashTable, isClass: bool): void {\n if (args) {\n var len = args.members.length;\n for (var i = 0; i < len; i++) {\n var local = <ArgDecl>args.members[i];\n if ((local.sym == null) ||\n (isClass || (local.sym.kind() != SymbolKind.Field))) {\n var result: Symbol = null;\n if ((result = table.lookup(local.id.text)) == null) {\n this.resolveBoundDecl(local);\n var localVar: ValueLocation = new ValueLocation();\n localVar.typeLink = new TypeLink();\n var varSym = new ParameterSymbol(local.id.text, local.minChar,\n this.checker.locationInfo.unitIndex,\n localVar);\n varSym.declAST = local;\n localVar.symbol = varSym;\n localVar.typeLink.type = local.type;\n localVar.symbol.container = container;\n local.sym = localVar.symbol;\n table.add(local.id.text, varSym);\n }\n else {\n local.type = result.getType();\n local.sym = result;\n }\n }\n }\n }\n }\n\n public checkInitSelf(funcDecl: FuncDecl): bool {\n if (!funcDecl.isMethod()) {\n var freeVars = funcDecl.freeVariables;\n for (var k = 0, len = freeVars.length; k < len; k++) {\n var sym = freeVars[k];\n if (sym.isInstanceProperty()) {\n return true;\n }\n }\n }\n var fns = funcDecl.scopes;\n var fnsLen = fns.members.length;\n\n for (var j = 0; j < fnsLen; j++) {\n var fn = <FuncDecl>fns.members[j];\n if (this.checkInitSelf(fn)) {\n return true;\n }\n }\n return false;\n }\n\n public checkPromoteFreeVars(funcDecl: FuncDecl, constructorSym: Symbol): void {\n var freeVars = funcDecl.freeVariables;\n for (var k = 0, len = freeVars.length; k < len; k++) {\n var sym = freeVars[k];\n if ((!sym.isInstanceProperty()) && (sym.container == constructorSym)) {\n instanceFilter.reset();\n if (this.scope.search(instanceFilter, sym.name, false, false)) {\n this.checker.errorReporter.simpleError(funcDecl, \"Constructor-local variable shadows class property '\" + sym.name + \"'. To access the class property, use 'self.\" + sym.name + \"'\");\n }\n\n this.checker.errorReporter.simpleError(funcDecl, \"Constructor-local variables may not be accessed from instance method bodies. Consider changing local variable '\" + sym.name + \"' to a class property\")\n }\n }\n }\n\n public allReturnsAreVoid(funcDecl: FuncDecl) {\n // in the case of a function or method with no declared return type, walk the body to \n // pre-emptively determine if the function has a return type of void\n //\n // REVIEW: Eventually, we'll want to perform exit graph analysis to determine\n // if the function ever \"escapes\" without a return expression\n // This would require moving some of this logic into the function's typecheck-proper,\n // which would slow things down a fair bit, but would open up more analysis opportunities\n var allReturnsAreVoid = true;\n\n if (funcDecl.signature.returnType.type == null) {\n var preFindReturnExpressionTypes = function (ast: AST, parent: AST, walker: IAstWalker) {\n var go = true;\n switch (ast.nodeType) {\n case NodeType.FuncDecl:\n // don't recurse into a function decl - we don't want to confuse a nested\n // return type with the top-level function's return type\n go = false;\n break;\n case NodeType.Return:\n var returnStmt: ReturnStatement = <ReturnStatement>ast;\n\n if (returnStmt.returnExpression) {\n allReturnsAreVoid = false;\n go = false;\n }\n\n default:\n break;\n }\n walker.options.goChildren = go;\n walker.options.goNextSibling = go;\n return ast;\n }\n\n getAstWalkerFactory().walk(funcDecl.bod, preFindReturnExpressionTypes);\n }\n\n return allReturnsAreVoid;\n }\n\n public classConstructorHasSuperCall(funcDecl: FuncDecl) {\n var foundSuper = false;\n\n var preFindSuperCall = function (ast: AST, parent: AST, walker: IAstWalker) {\n\n var go = true;\n\n switch (ast.nodeType) {\n case NodeType.FuncDecl:\n go = false;\n break;\n case NodeType.Call:\n var call = <CallExpression>ast;\n\n if (call.target.nodeType == NodeType.Super) {\n go = false;\n foundSuper = true;\n break;\n }\n break;\n default:\n break;\n }\n walker.options.goChildren = go;\n return ast;\n }\n\n getAstWalkerFactory().walk(funcDecl.bod, preFindSuperCall);\n\n return foundSuper;\n }\n\n private baseListPrivacyErrorReporter(bases: ASTList, i: number, declSymbol: Symbol, extendsList: bool, typeName: string, isModuleName: bool) {\n var baseSymbol = bases.members[i].type.symbol;\n var declTypeString = (declSymbol.declAST.nodeType == NodeType.InterfaceDeclaration) ? \"interface\" : \"class\";\n var baseListTypeString = extendsList ? \"extends\" : \"implements\";\n var baseTypeString = (baseSymbol.declAST.nodeType == NodeType.InterfaceDeclaration) ? \"interface\" : \"class\";\n var typestring = \"\";\n if (isModuleName) {\n var quotestring = \"\";\n if (!isQuoted(typeName)) {\n quotestring = \"'\";\n }\n typestring = \" is using inaccessible module \";\n baseTypeString = \" \" + baseTypeString + \" from private module \" + quotestring + typeName + quotestring;\n } else {\n baseTypeString = \" private \" + baseTypeString + \" '\" + typeName + \"'\";\n }\n this.checker.errorReporter.simpleError(bases.members[i], \"exported \" + declTypeString + \" '\" + declSymbol.name + \"' \" + baseListTypeString + baseTypeString);\n }\n\n // Check if declSymbol can satisfy baselist privacy\n private typeCheckBaseListPrivacy(bases: ASTList, declSymbol: Symbol, extendsList: bool) {\n if (bases) {\n var basesLen = bases.members.length;\n for (var i = 0; i < basesLen; i++) {\n if (!bases.members[i].type || bases.members[i].type == this.checker.anyType) {\n // This type is coming from external module so it has to be exported, or we're recovering from an\n // error condition\n continue;\n }\n\n this.checkSymbolPrivacy(bases.members[i].type.symbol, declSymbol, (typeName: string, isModuleName: bool) => this.baseListPrivacyErrorReporter(bases, i, declSymbol, extendsList, typeName, isModuleName));\n }\n }\n }\n\n // Checks if the privacy is satisfied by typeSymbol that is used in the declaration inside container\n private checkSymbolPrivacy(typeSymbol: TypeSymbol, declSymbol: Symbol, errorCallback: (typeName: string, isModuleName: bool) => void ) {\n var externalModuleSymbol: TypeSymbol = null;\n var declSymbolPath: Symbol[] = null;\n\n // Type is visible type, so this can be used by anyone.\n if (typeSymbol.isExternallyVisible(this.checker)) {\n // Symbol could be from external module, go ahead and find the external module\n var typeSymbolPath = typeSymbol.pathToRoot();\n declSymbolPath = declSymbol.pathToRoot();\n var typeSymbolLength = typeSymbolPath.length;\n var declSymbolPathLength = declSymbolPath.length;\n\n if (typeSymbolLength > 0) {\n if (typeSymbolPath[typeSymbolLength - 1].getType().isModuleType() &&\n (<TypeSymbol>typeSymbolPath[typeSymbolLength - 1]).isDynamic &&\n typeSymbolPath[typeSymbolLength - 1] != declSymbolPath[declSymbolPathLength - 1]) {\n // Symbol from external module that was imported using one of the import statement\n externalModuleSymbol = <TypeSymbol>typeSymbolPath[typeSymbolLength - 1];\n } else if (typeSymbolLength > 1) {\n // Is symbol from declared quoted module\n if (typeSymbolPath[typeSymbolLength - 2].getType().isModuleType() &&\n (<TypeSymbol>typeSymbolPath[typeSymbolLength - 2]).isDynamic &&\n (declSymbolPathLength == 1 || typeSymbolPath[typeSymbolLength - 2] != declSymbolPath[declSymbolPathLength - 2])) {\n // From quoted module name\n externalModuleSymbol = <TypeSymbol>typeSymbolPath[typeSymbolLength - 2];\n }\n }\n }\n\n if (externalModuleSymbol == null) {\n return;\n }\n }\n\n // Interface symbol doesn't reflect correct Exported state so use AST instead\n var interfaceDecl: InterfaceDeclaration = declSymbol.getInterfaceDeclFromSymbol(this.checker);\n if (interfaceDecl && !hasFlag(interfaceDecl.varFlags, VarFlags.Exported)) {\n return;\n }\n\n var checkVisibilitySymbol = declSymbol;\n // Var decl symbol doesnt reflect correct exported state so use AST instead\n var varDecl = declSymbol.getVarDeclFromSymbol();\n if (varDecl) {\n if (hasFlag(varDecl.varFlags, VarFlags.Private)) {\n return;\n } else if (hasFlag(varDecl.varFlags, VarFlags.Public)) {\n // Its a member from class so check visibility of its container\n checkVisibilitySymbol = declSymbol.container;\n }\n }\n\n // If the container is visible from global scrope it is error\n if (checkVisibilitySymbol.isExternallyVisible(this.checker)) {\n var privateSymbolName = typeSymbol.name;\n\n // If imported typeSymbol mark it as visible externally and verify that the symbol it imports is visible externally\n if (externalModuleSymbol != null) {\n var prettyName = externalModuleSymbol.getPrettyNameOfDynamicModule(declSymbolPath);\n if (prettyName != null) {\n this.currentScript.AddExternallyVisibleImportedSymbol(prettyName.symbol, this.checker);\n return;\n } else {\n privateSymbolName = externalModuleSymbol.prettyName;\n }\n }\n\n // Visible declaration using non visible type.\n errorCallback(privateSymbolName, typeSymbol.name != privateSymbolName);\n }\n }\n\n // Checks if the privacy is satisfied by type that is used in the declaration inside container\n private checkTypePrivacy(type: Type, declSymbol: Symbol, errorCallback: (typeName: string, isModuleName : bool) =>void ) {\n // Primitive types\n if (!(type && type.primitiveTypeClass == Primitive.None)) {\n return;\n }\n\n\n // If type is array, check element type\n if (type.isArray()) {\n return this.checkTypePrivacy(type.elementType, declSymbol, errorCallback);\n }\n\n // Going to be printing symbol name, verify if symbol can be emitted\n if (type.symbol && type.symbol.name && type.symbol.name != \"_anonymous\" &&\n (((type.call == null) && (type.construct == null) && (type.index == null)) ||\n (type.members && (!type.isClass())))) {\n return this.checkSymbolPrivacy(<TypeSymbol>type.symbol, declSymbol, errorCallback);\n }\n\n if (type.members) {\n // Verify symbols for members\n type.members.allMembers.map((key, s, unused) => {\n var sym = <Symbol>s;\n if (!hasFlag(sym.flags, SymbolFlags.BuiltIn)) {\n this.checkTypePrivacy(sym.getType(), declSymbol, errorCallback);\n }\n }, null);\n }\n\n this.checkSignatureGroupPrivacy(type.call, declSymbol, errorCallback);\n this.checkSignatureGroupPrivacy(type.construct, declSymbol, errorCallback);\n this.checkSignatureGroupPrivacy(type.index, declSymbol, errorCallback);\n }\n\n // Checks if the privacy is satisfied by typeSymbol that is used in the declaration inside container\n private checkSignatureGroupPrivacy(sgroup: SignatureGroup, declSymbol: Symbol, errorCallback: (typeName: string, isModuleName : bool) =>void ) {\n if (sgroup) {\n var len = sgroup.signatures.length;\n for (var i = 0; i < sgroup.signatures.length; i++) {\n var signature = sgroup.signatures[i];\n if (len > 1 && signature == sgroup.definitionSignature) {\n // In case of overloads don't look up for overload defintion types.\n continue;\n }\n\n if (signature.returnType) {\n this.checkTypePrivacy(signature.returnType.type, declSymbol, errorCallback);\n }\n\n var paramLen = signature.parameters.length;\n for (var j = 0; j < paramLen; j++) {\n var param = signature.parameters[j];\n this.checkTypePrivacy(param.getType(), declSymbol, errorCallback);\n }\n }\n }\n }\n\n private functionArgumentPrivacyErrorReporter(funcDecl: FuncDecl, p: number, paramSymbol: Symbol, typeName: string, isModuleName: bool) {\n var isGetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor);\n var isSetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.SetAccessor);\n var isPublicFunc = hasFlag(funcDecl.fncFlags, FncFlags.Public);\n var isContainerInterface = funcDecl.type.symbol.getInterfaceDeclFromSymbol(this.checker) != null;\n var typestring = \"\";\n if (isModuleName) {\n var quotestring = \"\";\n if (!isQuoted(typeName)) {\n quotestring = \"'\";\n }\n typestring = \" is using inaccessible module \" + quotestring + typeName + quotestring;\n } else {\n typestring = \" has or is using private type '\" + typeName + \"'\";\n }\n\n if (!isContainerInterface) {\n if (funcDecl.isConstructor) {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported class's constructor parameter '\" + paramSymbol.name + \"'\" + typestring);\n } else if (isSetter) {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], (isPublicFunc ? \"public\" : \"exported\") + \" setter parameter '\" + paramSymbol.name + \"'\" + typestring);\n } else if (!isGetter) {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], (isPublicFunc ? \"public\" : \"exported\") + \" function parameter '\" + paramSymbol.name + \"'\" + typestring);\n }\n } else {\n if (funcDecl.isConstructMember()) {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported interface's constructor parameter '\" + paramSymbol.name + \"'\" + typestring);\n } else if (funcDecl.isCallMember()) {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported interface's call parameter '\" + paramSymbol.name + \"'\" + typestring);\n } else if (!funcDecl.isIndexerMember()) {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported interface's function parameter '\" + paramSymbol.name + \"'\" + typestring);\n }\n }\n }\n\n private returnTypePrivacyError(astError: AST, funcDecl: FuncDecl, typeName: string, isModuleName: bool) {\n var isGetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor);\n var isSetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.SetAccessor);\n var isPublicFunc = hasFlag(funcDecl.fncFlags, FncFlags.Public);\n var isContainerInterface = funcDecl.type.symbol.getInterfaceDeclFromSymbol(this.checker) != null;\n var typestring = \"\";\n if (isModuleName) {\n var quotestring = \"\";\n if (!isQuoted(typeName)) {\n quotestring = \"'\";\n }\n typestring = \" is using inaccessible module \" + quotestring + typeName + quotestring;\n } else {\n typestring = \" has or is using private type '\" + typeName + \"'\";\n }\n if (!isContainerInterface) {\n if (isGetter) {\n this.checker.errorReporter.simpleError(astError, (isPublicFunc ? \"public\" : \"exported\") + \" getter return type\" + typestring);\n } else if (!isSetter) {\n this.checker.errorReporter.simpleError(astError, (isPublicFunc ? \"public\" : \"exported\") + \" function return type\" + typestring);\n }\n } else {\n if (funcDecl.isConstructMember()) {\n this.checker.errorReporter.simpleError(astError, \"exported interface's constructor return type\" + typestring);\n } else if (funcDecl.isCallMember()) {\n this.checker.errorReporter.simpleError(astError, \"exported interface's call return type\" + typestring);\n } else if (funcDecl.isIndexerMember()) {\n this.checker.errorReporter.simpleError(astError, \"exported interface's indexer return type\" + typestring);\n } else {\n this.checker.errorReporter.simpleError(astError, \"exported interface's function return type\" + typestring);\n }\n }\n }\n\n private functionReturnTypePrivacyErrorReporter(funcDecl: FuncDecl, signature: Signature, typeName: string, isModuleName: bool) {\n var reportOnFuncDecl = false;\n\n // Error coming from return annotation\n if (funcDecl.returnTypeAnnotation != null &&\n funcDecl.returnTypeAnnotation.type == signature.returnType.type) {\n this.returnTypePrivacyError(funcDecl.returnTypeAnnotation, funcDecl, typeName, isModuleName);\n }\n\n // Check if return statement's type matches the one that we concluded\n for (var i = 0; i < funcDecl.returnStatementsWithExpressions.length; i++) {\n if (funcDecl.returnStatementsWithExpressions[i].type == signature.returnType.type) {\n this.returnTypePrivacyError(funcDecl.returnStatementsWithExpressions[i], funcDecl, typeName, isModuleName);\n } else {\n reportOnFuncDecl = true;\n }\n }\n\n if (reportOnFuncDecl) {\n // Show on function decl\n this.returnTypePrivacyError(funcDecl, funcDecl, typeName, isModuleName);\n }\n }\n\n public typeCheckFunction(funcDecl: FuncDecl): FuncDecl {\n this.nestingLevel = 0;\n var fnType = funcDecl.type;\n\n var fgSym = fnType.symbol;\n var signature = funcDecl.signature;\n\n if (this.checker.typeStatusIsFinished(signature.typeCheckStatus)) {\n return funcDecl;\n }\n else if (signature.typeCheckStatus == TypeCheckStatus.Started) {\n if (!funcDecl.returnTypeAnnotation &&\n funcDecl.bod &&\n !funcDecl.isSignature() &&\n !(funcDecl.isConstructor) &&\n this.allReturnsAreVoid(funcDecl)) {\n\n signature.returnType.type = this.voidType;\n return funcDecl;\n }\n else {\n if (funcDecl.returnTypeAnnotation == null) {\n if (this.checker.styleSettings.implicitAny) {\n this.checker.errorReporter.styleError(funcDecl, \"type implicitly set to 'any'\");\n }\n signature.returnType.type = this.anyType;\n fgSym.flags |= SymbolFlags.RecursivelyReferenced;\n }\n return funcDecl;\n }\n }\n\n signature.typeCheckStatus = TypeCheckStatus.Started;\n this.checker.addStartedPTO(signature);\n var prevScope = this.scope;\n var prevFnc = this.thisFnc;\n var prevMethodStatus = this.enclosingFncIsMethod;\n var prevClassNode = this.thisClassNode;\n this.enclosingFncIsMethod = funcDecl.isMethod() || funcDecl.isConstructor;\n this.thisFnc = funcDecl;\n var container = funcDecl.type.symbol;\n var prevThisType = this.thisType;\n var prevLocationInfo = this.checker.locationInfo;\n var funcTable: IHashTable = null;\n var acceptedContextualType = false;\n var targetParams: ParameterSymbol[] = null;\n var targetReturnType: Type = null;\n var isGetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor);\n var isSetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.SetAccessor);\n var accessorType: Type = (isGetter || isSetter) && funcDecl.accessorSymbol ? funcDecl.accessorSymbol.getType() : null;\n var prevModDecl = this.checker.currentModDecl;\n\n if (funcDecl.isConstructor && !funcDecl.isOverload) {\n if (fnType.instanceType == null) {\n this.checker.errorReporter.simpleError(funcDecl, \"Malformed function body (is this a class named the same as an existing interface?)\");\n return funcDecl;\n }\n\n this.scope = fnType.instanceType.constructorScope;\n var ssb = <SymbolScopeBuilder>this.scope;\n funcTable = ssb.valueMembers.allMembers;\n }\n else if ((funcDecl.isSpecialFn() && !(funcDecl.fncFlags & FncFlags.Signature)) || funcDecl.isOverload) {\n funcTable = funcDecl.symbols;\n // if the function is static, we just want to use the \n // current scope\n if (!hasFlag(funcDecl.fncFlags, FncFlags.Static) && fnType.containedScope) {\n this.scope = fnType.containedScope;\n }\n }\n else {\n if (funcDecl.bod) {\n this.scope = fnType.containedScope;\n }\n var ssb = <SymbolScopeBuilder>this.scope;\n\n // If it is null, it's an ambient declaration with no body, so it doesn't strictly matter\n // if funcTable is not set\n if (ssb && ssb.valueMembers) {\n funcTable = ssb.valueMembers.allMembers;\n }\n }\n\n // If it's a class constructor, we need to check for the presence (or absense) of calls\n // to the 'super' constructor\n //\n // A super constructor call must exist if:\n // - the class has a base class\n //\n // A super constructor call must be the first statement in the function body if:\n // - the constructor has parameter properties or\n // - the class body has initialized property decls\n //\n // A super constructor call may not exist if:\n // - The class has no base type, or inherits directly from 'Object'\n if (funcDecl.isConstructor && funcDecl.bod && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n\n var hasBaseType = hasFlag(funcDecl.classDecl.type.instanceType.typeFlags, TypeFlags.HasBaseType);\n var noSuperCallAllowed = !hasBaseType || hasFlag(funcDecl.classDecl.type.instanceType.typeFlags, TypeFlags.HasBaseTypeOfObject);\n var superCallMustBeFirst = hasFlag((<ClassDeclaration>funcDecl.classDecl).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor);\n\n if (noSuperCallAllowed && this.classConstructorHasSuperCall(funcDecl)) {\n this.checker.errorReporter.simpleError(funcDecl, \"Calls to 'super' constructor are not allowed in classes that either inherit directly from 'Object' or have no base class\");\n }\n else if (hasBaseType) {\n if (superCallMustBeFirst) {\n if (!funcDecl.bod ||\n !funcDecl.bod.members.length ||\n !((funcDecl.bod.members[0].nodeType == NodeType.Call && (<CallExpression>funcDecl.bod.members[0]).target.nodeType == NodeType.Super) ||\n (hasFlag(funcDecl.bod.flags, ASTFlags.StrictMode) && funcDecl.bod.members.length > 1 &&\n funcDecl.bod.members[1].nodeType == NodeType.Call && (<CallExpression>funcDecl.bod.members[1]).target.nodeType == NodeType.Super))) {\n this.checker.errorReporter.simpleError(funcDecl, \"If a derived class contains initialized properties or constructor parameter properties, the first statement in the constructor body must be a call to the super constructor\");\n }\n }\n else if (!this.classConstructorHasSuperCall(funcDecl)) {\n this.checker.errorReporter.simpleError(funcDecl, \"Constructors for derived classes must contain a call to the class's 'super' constructor\");\n }\n }\n }\n\n // If we've typechecked this method \"out of order\" (not by walking the class, but through a method call somewhere else),\n // we need to reset the current class node in question, so that visibility checks on class members don't fail\n if (funcDecl.isMethod() && funcDecl.type.enclosingType) {\n\n var enclosingClassNode: TypeDeclaration = null;\n\n if (funcDecl.type.enclosingType.symbol.declAST.nodeType == NodeType.FuncDecl) {\n enclosingClassNode = <TypeDeclaration>(<FuncDecl>funcDecl.type.enclosingType.symbol.declAST).classDecl;\n }\n else if (funcDecl.type.enclosingType.symbol.declAST.nodeType == NodeType.ClassDeclaration) {\n enclosingClassNode = <TypeDeclaration>funcDecl.type.enclosingType.symbol.declAST;\n }\n\n if (enclosingClassNode) {\n this.thisClassNode = enclosingClassNode;\n }\n }\n\n // if this function is contained in a module, we may be in the midst of a recursive typecheck operation\n // should that be the case, we need to properly set the current module (for visibility tests)\n if (fnType.enclosingType) {;\n var enclosingSym = fnType.symbol.container;\n\n // if the enclosing type is a class, grab the parent module\n if (enclosingSym && enclosingSym.isType() && enclosingSym.getType().isClass()) {\n enclosingSym = enclosingSym.container;\n }\n\n if (enclosingSym && enclosingSym.declAST && enclosingSym.declAST.nodeType == NodeType.ModuleDeclaration) {\n this.checker.currentModDecl = <ModuleDeclaration>enclosingSym.declAST;\n }\n }\n\n if (funcDecl.unitIndex > 0) {\n if (this.checker.units &&\n (funcDecl.unitIndex < this.checker.units.length)) {\n this.checker.locationInfo = this.checker.units[funcDecl.unitIndex];\n }\n else {\n this.checker.locationInfo = unknownLocationInfo;\n }\n }\n\n if (fnType.enclosingType) {\n this.thisType = fnType.enclosingType;\n }\n else {\n this.thisType = prevThisType;\n }\n\n var paramLen = signature.parameters.length;\n\n if (!funcDecl.isConstructor && funcDecl.bod && !funcDecl.isSignature()) {\n var tmpParamScope = this.scope;\n var ssb = <SymbolScopeBuilder>this.scope;\n\n // Attempt to contextually type the function declaration \n if (!funcDecl.isMethod() && funcDecl.returnTypeAnnotation == null) {\n\n // the funcDecl may be a candidate for contextual typing \n // REVIEW: prevScope will only be null in the case of an upstream error\n if (prevScope && funcDecl.name && !funcDecl.name.isMissing()) {\n // Go ahead and check for an ambient symbol\n var considerSym: Symbol = prevScope.findAmbient(funcDecl.name.text, false, false);\n\n if (considerSym && considerSym.declAST && considerSym.declAST.type) {\n // REVIEW: Ambients beget signatures, and signatures don't need to be typechecked\n //typeCheck(considerSym.declAST);\n this.checker.setContextualType(considerSym.declAST.type, false);\n }\n }\n\n if (this.checker.hasTargetType()) {\n var candidateTypeContext = this.checker.getTargetTypeContext();\n var candidateType = candidateTypeContext.contextualType;\n\n if (this.checker.canContextuallyTypeFunction(candidateType, funcDecl, true)) {\n\n // Safe to do this, since the indices and fields are guaranteed to be\n // non-null and valid by the above call to canContextuallyTypeFunction\n var candidateSigs = candidateType.construct ? candidateType.construct : candidateType.call;\n candidateTypeContext.targetSig = candidateSigs.signatures[0];\n var candidateParams = candidateTypeContext.targetSig.parameters;\n\n // the target type has been accepted\n targetParams = candidateParams;\n targetReturnType = candidateTypeContext.targetSig.returnType.type;\n\n // Set \"this\" if applicable\n if (candidateTypeContext.targetSig.declAST) {\n if (candidateTypeContext.targetSig.declAST.isConstructor) {\n //candidateTypeContext.targetThis=candidateType.instanceType;\n //this.thisType = candidateType.instanceType;\n funcDecl.isTargetTypedAsMethod = true;\n }\n else if (candidateTypeContext.targetSig.declAST.isMethod()) {\n //candidateTypeContext.targetThis=candidateTypeContext.targetSig.declAST.type.enclosingType;\n //this.thisType = candidateTypeContext.targetSig.declAST.type.enclosingType;\n funcDecl.isTargetTypedAsMethod = true;\n }\n }\n fgSym.type = candidateTypeContext.contextualType;\n acceptedContextualType = true;\n }\n else if (candidateType && funcDecl.isAccessor()) {\n accessorType = candidateType;\n candidateTypeContext.targetAccessorType = accessorType;\n }\n else {\n this.checker.killCurrentContextualType();\n }\n }\n }\n\n // typecheck parameters\n // Add parameter symbols to current scope for typechecking (in case default params reference each other)\n // Order matters here - default parameters can reference previously defined parameters\n var paramTable = ssb.valueMembers;\n this.scope = new SymbolScopeBuilder(paramTable, null, null, null, prevScope, container);\n\n for (var p = 0; p < paramLen; p++) {\n var symbol = signature.parameters[p];\n var ast = <ArgDecl>symbol.declAST\n\n if (this.checker.hasTargetType() && (targetParams && (this.checker.getTargetTypeContext().targetSig.hasVariableArgList || p < targetParams.length))) {\n var candidateTypeContext = this.checker.getTargetTypeContext();\n var hasVarArgList = candidateTypeContext.targetSig.hasVariableArgList;\n ast.type = hasVarArgList && p >= targetParams.length - 1 ? targetParams[targetParams.length - 1].getType().elementType : targetParams[p].getType();\n ast.sym.setType(ast.type);\n (<InferenceSymbol>ast.sym).typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n }\n else {\n this.typeCheck(ast);\n }\n\n // infer the setter type, if necessary\n if (isSetter && accessorType) {\n ast = <ArgDecl>this.cast(ast, accessorType);\n }\n\n symbol.container = container;\n // Verify the parameter for the privacy\n this.checkTypePrivacy(symbol.getType(), container, (typeName: string, isModuleName: bool) => this.functionArgumentPrivacyErrorReporter(funcDecl, p, symbol, typeName, isModuleName));\n paramTable.publicMembers.add(symbol.name, symbol);\n }\n this.scope = tmpParamScope;\n }\n else {\n this.typeCheck(funcDecl.arguments)\n\n // Because some terms were not yet type-checkable during binding, ensure that\n // param symbols are updated with the proper argument types\n for (var p = 0; p < paramLen; p++) {\n signature.parameters[p].parameter.typeLink.type = funcDecl.arguments.members[p].type;\n // Verify the parameter for the privacy\n this.checkTypePrivacy(signature.parameters[p].getType(), container, (typeName: string, isModuleName: bool) => this.functionArgumentPrivacyErrorReporter(funcDecl, p, signature.parameters[p], typeName, isModuleName));\n if ((<ArgDecl>funcDecl.arguments.members[p]).parameterPropertySym) {\n (<ArgDecl>funcDecl.arguments.members[p]).parameterPropertySym.setType(funcDecl.arguments.members[p].type);\n }\n }\n\n if ((funcDecl.fncFlags & FncFlags.IndexerMember)) {\n if (!paramLen || paramLen > 1) {\n this.checker.errorReporter.simpleError(funcDecl, \"Index signatures may take one and only one parameter\");\n }\n else if (funcDecl.arguments.members[0].type == this.checker.numberType) {\n fnType.index.flags |= SignatureFlags.IsNumberIndexer;\n }\n else if (funcDecl.arguments.members[0].type == this.checker.stringType) {\n fnType.index.flags |= SignatureFlags.IsStringIndexer;\n }\n else {\n this.checker.errorReporter.simpleError(funcDecl.arguments.members[0], \"Index signatures may only take 'string' or 'number' as their parameter\");\n }\n\n }\n }\n\n // typecheck body\n if (funcDecl.bod && (!funcDecl.isSignature())) {\n if (!(funcDecl.isConstructor)) {\n this.addFormals(container, signature, funcTable);\n }\n else {\n this.addConstructorLocalArgs(funcDecl.type.symbol, funcDecl.arguments, funcTable, hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod));\n\n if (this.thisClassNode && this.thisClassNode.extendsList) {\n var tmpScope = this.scope;\n var funcMembers = new ScopedMembers(<DualStringHashTable>funcTable);\n this.scope = new FilteredSymbolScopeBuilder(funcMembers, prevScope, funcDecl.type.symbol,\n function (sym) {\n return sym.kind() == SymbolKind.Parameter;\n });\n this.typeCheckBaseCalls(this.thisClassNode.extendsList);\n this.scope = tmpScope;\n }\n }\n\n // Because this function may have been typechecked in a different visiblity context as its caller (e.g., this\n // function is being typechecked as a result of a call, before the declaration could be typechecked), we need\n // to set the enclosing module\n var prevMod = this.checker.currentModDecl;\n if (funcDecl.type &&\n funcDecl.type.symbol &&\n !funcDecl.isMethod() &&\n funcDecl.type.symbol.declModule) {\n this.checker.currentModDecl = funcDecl.type.symbol.declModule;\n }\n\n\n // unset the contextual type before typechecking the function body\n if (acceptedContextualType) {\n this.checker.setContextualType(null, this.checker.inProvisionalTypecheckMode());\n }\n\n this.typeCheck(funcDecl.bod);\n\n if (acceptedContextualType) {\n this.checker.unsetContextualType();\n }\n\n this.checker.currentModDecl = prevMod;\n\n if (this.checker.checkControlFlow) {\n var cfg = funcDecl.buildControlFlow();\n if (this.checker.printControlFlowGraph) {\n cfg.print(this.checker.errorReporter.outfile);\n }\n cfg.reportUnreachable(this.checker.errorReporter);\n if (this.checker.checkControlFlowUseDef) {\n cfg.useDef(this.checker.errorReporter, funcDecl.type.symbol);\n }\n }\n\n if (funcDecl.isConstructor) {\n var fns: ASTList = funcDecl.scopes;\n var fnsLen = fns.members.length;\n var freeVars: Symbol[];\n var sym: Symbol;\n var j = 0;\n for (; j < fnsLen; j++) {\n var fn = <FuncDecl>fns.members[j];\n if (!fn.isSignature()) {\n if (hasFlag(fn.fncFlags, FncFlags.Method) && (!hasFlag(fn.fncFlags, FncFlags.Static))) {\n this.checkPromoteFreeVars(fn, funcDecl.type.symbol);\n }\n }\n }\n }\n }\n\n this.scope = prevScope;\n this.thisFnc = prevFnc;\n this.thisClassNode = prevClassNode;\n this.enclosingFncIsMethod = prevMethodStatus;\n this.thisType = prevThisType;\n this.checker.locationInfo = prevLocationInfo;\n this.checker.currentModDecl = prevModDecl;\n\n signature.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n\n // set the return type\n if (funcDecl.returnTypeAnnotation) {\n this.checkForVoidConstructor(funcDecl.returnTypeAnnotation.type, funcDecl.returnTypeAnnotation);\n\n if (signature.returnType.type == null) {\n this.checker.resolveTypeLink(this.scope, signature.returnType, false);\n }\n }\n else if (targetReturnType) {\n signature.returnType.type = targetReturnType;\n }\n\n // If no return type annotation has been applied to the function declaration\n // unify the return types from the given return statements\n\n if (!(fgSym.flags & SymbolFlags.RecursivelyReferenced) && funcDecl.returnStatementsWithExpressions.length > 0) {\n var collection: ITypeCollection = {\n getLength: () => { return funcDecl.returnStatementsWithExpressions.length; },\n setTypeAtIndex: (index: number, type: Type) => { funcDecl.returnStatementsWithExpressions[index].type = type; },\n getTypeAtIndex: (index: number) => { return funcDecl.returnStatementsWithExpressions[index].type; }\n }\n\n var bestCommonReturnType = funcDecl.returnStatementsWithExpressions[0].type;\n bestCommonReturnType = this.checker.findBestCommonType(bestCommonReturnType, null, collection, true);\n\n if (bestCommonReturnType) {\n signature.returnType.type = this.checker.widenType(bestCommonReturnType);\n }\n else {\n for (var i = 0; i < funcDecl.returnStatementsWithExpressions.length; i++) {\n this.checker.errorReporter.simpleError(funcDecl.returnStatementsWithExpressions[i], \"Incompatible return type\");\n }\n signature.returnType.type = this.anyType;\n }\n }\n\n var onlyHasThrow = false;\n\n if (signature.returnType.type == null) {\n if (hasFlag(funcDecl.fncFlags, FncFlags.HasReturnExpression)) {\n if (this.checker.styleSettings.implicitAny) {\n this.checker.errorReporter.styleError(funcDecl, \"type implicitly set to 'any'\");\n }\n signature.returnType.type = this.anyType;\n }\n else {\n signature.returnType.type = this.voidType;\n }\n }\n else if (signature.returnType.type == this.nullType || signature.returnType.type == this.checker.undefinedType) {\n signature.returnType.type = this.anyType;\n }\n else if ((signature.returnType.type != this.voidType && signature.returnType.type != this.checker.undefinedType && signature.returnType.type != this.anyType)) {\n // the signature declared a non-void type, but there's no return statement\n if (!funcDecl.isSignature() &&\n !funcDecl.isConstructor &&\n !hasFlag(funcDecl.fncFlags, FncFlags.HasReturnExpression) &&\n !hasFlag(funcDecl.fncFlags, FncFlags.IsFatArrowFunction)) {\n // relax the restriction if the method only contains a single \"throw\" statement\n onlyHasThrow = (funcDecl.bod.members.length > 0) && (funcDecl.bod.members[0].nodeType == NodeType.Throw)\n\n if (!onlyHasThrow) {\n this.checker.errorReporter.simpleError(funcDecl.returnTypeAnnotation || funcDecl,\n \"Function declared a non-void return type, but has no return expression\");\n }\n }\n\n // Type check for return type Privacy\n this.checkTypePrivacy(signature.returnType.type, container, (typeName: string, isModuleName: bool) => this.functionReturnTypePrivacyErrorReporter(funcDecl, signature, typeName, isModuleName));\n }\n\n // if the function declaration is a getter or a setter, set the type of the associated getter/setter symbol\n if (funcDecl.accessorSymbol) {\n var accessorType = funcDecl.accessorSymbol.getType();\n if (!onlyHasThrow && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor) && !hasFlag(funcDecl.fncFlags, FncFlags.HasReturnExpression)) {\n this.checker.errorReporter.simpleError(funcDecl, \"Getters must return a value\");\n }\n if (accessorType) {\n if ((hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor) && accessorType != signature.returnType.type) ||\n (funcDecl.arguments.members.length > 0 && accessorType != funcDecl.arguments.members[0].type)) {\n this.checker.errorReporter.simpleError(funcDecl, \"Getter and setter types do not agree\");\n }\n }\n else {\n if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n funcDecl.accessorSymbol.setType(signature.returnType.type);\n }\n else {\n if (funcDecl.arguments.members.length != 1) {\n this.checker.errorReporter.simpleError(funcDecl, \"Setters may have one and only one argument\");\n }\n else {\n funcDecl.accessorSymbol.setType(funcDecl.arguments.members[0].type);\n }\n }\n }\n }\n\n this.typeCheckOverloadSignatures(fnType, funcDecl);\n return funcDecl;\n }\n\n public typeCheckBases(type: Type) {\n var seenInterface = false;\n var bases = type.extendsList;\n var baseLinks = type.extendsTypeLinks;\n if (bases) {\n var len = bases.length;\n\n if (len > 0) {\n type.typeFlags |= TypeFlags.HasBaseType;\n }\n\n for (var i = 0; i < len; i++) {\n if (bases[i] == this.checker.anyType) {\n // This may be the type from imported module and hence the type was not really resolved to the correct one.\n // Try resolving it again\n baseLinks[i].type = null;\n // There are no contextual errors when trying to verify the base class\n var oldErrors = this.checker.errorReporter.getCapturedErrors();\n CompilerDiagnostics.assert(oldErrors.length == 0, \"There shouldnt be any contextual errors when typechecking base type names\");\n this.checker.errorReporter.pushToErrorSink = true;\n bases[i] = this.checker.resolveBaseTypeLink(baseLinks[i], type.containedScope);\n this.checker.errorReporter.pushToErrorSink = false;\n this.checker.errorReporter.freeCapturedErrors();\n }\n\n var base = bases[i];\n var baseRef = baseLinks[i].ast;\n\n // make sure it's the global 'Object' and not some alias\n var baseTypeOfObject = base.symbol && base.symbol.name == \"Object\" && base.symbol.container == this.checker.gloMod;\n\n if (baseTypeOfObject) {\n type.typeFlags |= TypeFlags.HasBaseTypeOfObject;\n }\n\n if (base.isClassInstance()) {\n if (!(type.isClassInstance())) {\n this.checker.errorReporter.simpleError(baseRef, \"Interface base type must be interface\");\n }\n else {\n if (seenInterface) {\n this.checker.errorReporter.simpleError(baseRef, \"Class may not follow interface as base type\");\n }\n }\n }\n else if (base.isModuleType()) {\n this.checker.errorReporter.simpleError(baseRef, \"Types may not be derived from module types\");\n }\n else if (base.members) {\n if (!seenInterface) {\n seenInterface = true;\n }\n }\n else {\n if (!(type.isClassInstance())) {\n this.checker.errorReporter.simpleError(baseRef,\n \"Interface base type must be interface\");\n }\n else {\n this.checker.errorReporter.simpleError(baseRef,\n \"Base type must be interface or class\");\n }\n break;\n }\n }\n }\n }\n\n public checkMembersImplementInterfaces(implementingType: Type) {\n var instanceType = implementingType.getInstanceType();\n if (instanceType.implementsList) {\n var len = instanceType.implementsList.length;\n\n for (var i = 0; i < len; i++) {\n var interfaceType = instanceType.implementsList[i];\n var comparisonInfo = new TypeComparisonInfo();\n if (!this.checker.sourceIsSubtypeOfTarget(instanceType, interfaceType, comparisonInfo)) {\n var emsg = \"Class '\" + instanceType.getTypeName() +\n \"' declares interface '\" + interfaceType.getTypeName() +\n \"' but does not implement it\";\n if (!comparisonInfo.message) {\n this.checker.errorReporter.simpleErrorFromSym(instanceType.symbol, emsg);\n }\n else {\n this.checker.errorReporter.simpleErrorFromSym(instanceType.symbol, emsg + \": \" + comparisonInfo.message);\n }\n }\n }\n }\n }\n\n public typeCheckBaseCalls(bases: ASTList) {\n if (bases == null) {\n return;\n }\n var basesLen = bases.members.length;\n for (var i = 0; i < basesLen; i++) {\n var baseExpr = bases.members[i];\n var baseSymbol: Symbol = null;\n if (baseExpr.nodeType == NodeType.Call) {\n this.typeCheckNew(baseExpr);\n }\n }\n }\n\n public assertUniqueNamesInBaseTypes(names: IHashTable, type: Type, classDecl: InterfaceDeclaration, checkUnique: bool): void {\n if (type) {\n if (type.members) {\n type.members.publicMembers.map((key, s, c) => {\n var sym = <Symbol>s;\n var dup = names.lookup(sym.name);\n if (dup) {\n if (checkUnique) {\n this.checker.errorReporter.simpleError(classDecl,\n \"duplicate member name in bases for \" + classDecl.name.actualText + \": \" + type.symbol.name + \" and \" + dup.container.name + \" both contain member with name \" + sym.name);\n }\n }\n else {\n names.add(sym.name, sym);\n }\n }, null);\n }\n if (type.extendsList) {\n var len = type.extendsList.length;\n for (var i = 0; i < len; i++) {\n if (!(type.extendsList[i].symbol.flags & SymbolFlags.RecursivelyReferenced)) {\n this.assertUniqueNamesInBaseTypes(names, type.extendsList[i], classDecl, checkUnique);\n }\n }\n }\n }\n }\n\n public checkBaseTypeMemberInheritance(derivedType: Type, derivedTypeDecl: AST): void {\n var instanceType = derivedType.getInstanceType();\n if (instanceType.extendsList == null) {\n return;\n }\n\n var len = instanceType.extendsList.length;\n if (len > 0) {\n var names = new StringHashTable();\n if (instanceType.isClassInstance()) {\n for (var i = 0; i < len; i++) {\n this.assertUniqueNamesInBaseTypes(names, instanceType.extendsList[i], <InterfaceDeclaration>derivedTypeDecl, i > 0);\n }\n }\n\n if (instanceType.members) {\n instanceType.members.publicMembers.map((key, s, c) => {\n var sym = <Symbol>s;\n for (var j = 0; j < len; j++) {\n var base = instanceType.extendsList[j];\n if (base.memberScope == null) {\n this.checker.errorReporter.simpleError(derivedTypeDecl, \"Base type '\" + base.symbol.name + \"' lacks an implementation.\")\n }\n else {\n var bSym = base.memberScope.find(sym.name, false, false);\n if (bSym) {\n var aType = sym.getType();\n var bType = bSym.getType();\n if (!(this.checker.sourceIsSubtypeOfTarget(aType, bType))) {\n this.checker.errorReporter.simpleErrorFromSym(sym,\n \"Type of overridden member '\" + sym.name + \"' is not subtype of original member defined by type '\" + bSym.container.name + \"'\");\n }\n else if ((sym.kind() == SymbolKind.Type) &&\n (bSym.kind() == SymbolKind.Field)) {\n this.checker.errorReporter.simpleErrorFromSym(sym,\n \"Cannot override field '\" + sym.name + \"' with method\");\n }\n }\n }\n }\n }, null);\n }\n }\n }\n\n public typeCheckClass(classDecl: ClassDeclaration): ClassDeclaration {\n var typeSymbol = <TypeSymbol>classDecl.type.symbol;\n\n if (typeSymbol.typeCheckStatus == TypeCheckStatus.Finished) {\n return classDecl;\n }\n else if (typeSymbol.typeCheckStatus == TypeCheckStatus.Started) {\n // REVIEW: report this recursion\n //checker.errorReporter.recursionRequiresTypeAnnotation(classDecl);\n return classDecl;\n }\n else {\n typeSymbol.typeCheckStatus = TypeCheckStatus.Started;\n this.checker.addStartedPTO(typeSymbol);\n }\n\n var prevScope = this.scope;\n var svClassNode = this.thisClassNode;\n this.thisClassNode = classDecl;\n var classType = classDecl.type;\n this.typeCheckBases(classType.instanceType);\n\n this.typeCheckBaseListPrivacy(classDecl.extendsList, typeSymbol, true);\n this.typeCheckBaseListPrivacy(classDecl.implementsList, typeSymbol, false);\n\n var prevThisType = this.thisType;\n this.thisType = classType.instanceType;\n this.scope = classType.instanceType.containedScope;\n\n // Add the constructor locals, if necessary\n if (classDecl.constructorDecl) {\n this.scope = classType.instanceType.constructorScope;\n var ssb = <SymbolScopeBuilder>this.scope;\n var funcTable = ssb.valueMembers.allMembers;\n\n this.addConstructorLocalArgs(classDecl.constructorDecl.type.symbol, classDecl.constructorDecl.arguments, funcTable, true);\n }\n\n this.typeCheck(classDecl.members);\n typeSymbol.typeCheckStatus = TypeCheckStatus.Finished;\n this.checkBaseTypeMemberInheritance(classType, classDecl);\n this.checkMembersImplementInterfaces(classType);\n\n this.typeCheckOverloadSignatures(classType, classDecl);\n this.typeCheckOverloadSignatures(classType.instanceType, classDecl);\n\n // if the class has no declared constructor, adapt its base class's signature group, if necessary\n if (!classDecl.constructorDecl) {\n if (classDecl.extendsList &&\n classDecl.extendsList.members.length &&\n classDecl.extendsList.members[0].type &&\n classDecl.extendsList.members[0].type.symbol.type.isClass()) {\n cloneParentConstructGroupForChildType(classDecl.type, classDecl.extendsList.members[0].type.symbol.type);\n }\n }\n\n this.thisType = prevThisType;\n this.thisClassNode = svClassNode;\n this.scope = prevScope;\n return classDecl;\n }\n\n public typeCheckOverloadSignatures(type: Type, ast: AST) {\n if (type.call) {\n type.call.typeCheck(this.checker, ast, type.construct != null);\n }\n if (type.construct) {\n type.construct.typeCheck(this.checker, ast, false);\n }\n if (type.index) {\n type.index.typeCheck(this.checker, ast, false);\n }\n }\n\n public typeCheckInterface(interfaceDecl: InterfaceDeclaration): InterfaceDeclaration {\n // overloads will be typechecked inline by the members\n //this.typeCheckOverloadSignatures(interfaceDecl.type, interfaceDecl);\n this.typeCheckBases(interfaceDecl.type);\n this.typeCheckBaseListPrivacy(interfaceDecl.extendsList, interfaceDecl.type.symbol, true);\n this.typeCheck(interfaceDecl.members);\n this.checkBaseTypeMemberInheritance(interfaceDecl.type, interfaceDecl);\n\n // propagate base type signatures\n if (interfaceDecl.extendsList) {\n for (var i = 0; i < interfaceDecl.extendsList.members.length; i++) {\n if (interfaceDecl.extendsList.members[i].type.call) {\n if (interfaceDecl.type.call) {\n interfaceDecl.type.call.signatures = interfaceDecl.type.call.signatures.concat(interfaceDecl.extendsList.members[i].type.call.signatures);\n }\n else {\n interfaceDecl.type.call = interfaceDecl.extendsList.members[i].type.call;\n }\n }\n if (interfaceDecl.extendsList.members[i].type.construct) {\n if (interfaceDecl.type.construct) {\n interfaceDecl.type.construct.signatures = interfaceDecl.type.construct.signatures.concat(interfaceDecl.extendsList.members[i].type.construct.signatures);\n }\n else {\n interfaceDecl.type.construct = interfaceDecl.extendsList.members[i].type.construct;\n }\n }\n if (interfaceDecl.extendsList.members[i].type.index) {\n if (interfaceDecl.type.index) {\n interfaceDecl.type.index.signatures = interfaceDecl.type.index.signatures.concat(interfaceDecl.extendsList.members[i].type.index.signatures);\n }\n else {\n interfaceDecl.type.index = interfaceDecl.extendsList.members[i].type.index;\n }\n }\n }\n }\n\n return interfaceDecl;\n }\n\n public typeCheckImportDecl(importDecl: ImportDeclaration) {\n var mod: ModuleType = <ModuleType>importDecl.alias.type;\n var sym: TypeSymbol = null;\n var prevInImportTC = this.inImportTypeCheck;\n this.inImportTypeCheck = true;\n\n this.typeCheck(importDecl.alias);\n mod = <ModuleType>importDecl.alias.type;\n\n if (mod == null) {\n this.checker.errorReporter.simpleError(importDecl.alias, \"Could not resolve module alias '\" + importDecl.id.actualText + \"'\");\n mod = <ModuleType>this.checker.anyType;\n (<TypeSymbol>importDecl.id.sym).type = mod;\n }\n\n importDecl.id.type = mod;\n sym = mod.symbol;\n\n if (!mod.isModuleType()) {\n this.checker.errorReporter.simpleError(importDecl.alias, \"A module cannot be aliased to a non-module type\");\n }\n else {\n sym.type = mod;\n \n // Add the imported module to the AMD dependency list\n if (this.checker.typeFlow.currentScript && \n this.checker.typeFlow.currentScript.topLevelMod && \n this.checker.typeFlow.currentScript.topLevelMod.mod) \n {\n this.checker.typeFlow.currentScript.topLevelMod.mod.importedModules.push(importDecl);\n }\n\n (<TypeSymbol>importDecl.id.sym).type = mod;\n\n if (mod.symbol && mod.symbol.declAST) {\n (<ModuleDeclaration>mod.symbol.declAST).modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;\n }\n\n //importDecl.id.sym = sym;\n // REVIEW: Uncomment when you can toggle module codegen targets from the language service\n //else if (typeFlow.checker.currentModDecl == null && \n // hasFlag((<ModuleDecl>sym.declAST).modFlags,ModuleFlags.IsDynamic) &&\n // moduleGenTarget == ModuleGenTarget.Asynchronous) \n //{\n // typeFlow.checker.errorReporter.simpleError(alias, \"In AMD codegen mode, dynamic modules may not be referenced from global scope. (Wrap the file in a module declaration.)\");\n //}\n }\n this.inImportTypeCheck = prevInImportTC;\n return importDecl;\n }\n\n public typeCheckModule(moduleDecl: ModuleDeclaration): ModuleDeclaration {\n\n // In some really nasty cases of error recovery, we may not have a type\n if (!moduleDecl.mod) {\n return moduleDecl;\n }\n\n if (this.currentScript) {\n this.currentScript.requiresGlobal = true;\n }\n var mod = moduleDecl.mod;\n var sym: TypeSymbol = null;\n\n var prevScope = this.scope;\n var prevThisType = this.thisType;\n var prevCurrentModDecl = this.checker.currentModDecl;\n this.checker.currentModDecl = moduleDecl;\n\n this.thisType = null;\n this.scope = mod.containedScope;\n this.typeCheck(moduleDecl.members);\n sym = mod.symbol;\n\n this.checker.currentModDecl = prevCurrentModDecl;\n this.thisType = prevThisType;\n this.scope = prevScope;\n\n moduleDecl.type = mod;\n\n if (sym) {\n sym.typeCheckStatus = TypeCheckStatus.Finished;\n }\n return moduleDecl;\n }\n\n public typeCheckFor(forStmt: ForStatement): ForStatement {\n forStmt.init = this.typeCheck(forStmt.init);\n this.nestingLevel++;\n forStmt.cond = this.typeCheck(forStmt.cond);\n this.typeCheckCondExpr(forStmt.cond);\n forStmt.incr = this.typeCheck(forStmt.incr);\n this.nestingLevel--;\n forStmt.body = this.typeCheck(forStmt.body);\n this.typeCheckCompoundStmtBlock(forStmt.body, \"for statement\");\n forStmt.type = this.voidType;\n return forStmt;\n }\n\n public typeCheckWith(withStmt: WithStatement): WithStatement {\n if (this.checker.errorsOnWith) {\n this.checker.errorReporter.simpleError(withStmt.expr, \"All symbols within a 'with' block will be typed as 'any'\");\n }\n withStmt.expr = this.typeCheck(withStmt.expr);\n this.checker.inWith = true;\n withStmt.body = this.typeCheck(withStmt.body);\n this.typeCheckCompoundStmtBlock(withStmt.body, \"with statement\");\n this.checker.inWith = false;\n return withStmt;\n }\n\n public typeCheckForIn(forInStmt: ForInStatement): ForInStatement {\n forInStmt.obj = this.typeCheck(forInStmt.obj);\n forInStmt.lval = this.cast(this.typeCheck(forInStmt.lval), this.checker.stringType);\n if (forInStmt.lval.nodeType == NodeType.VarDecl) {\n\n var varDecl = <VarDecl>forInStmt.lval;\n if (varDecl.typeExpr) {\n this.checker.errorReporter.simpleError(varDecl, \"Variable declarations for for/in expressions may not contain a type annotation\");\n }\n\n if (varDecl.sym) {\n varDecl.sym.setType(this.checker.stringType);\n }\n }\n forInStmt.body = this.typeCheck(forInStmt.body);\n this.typeCheckCompoundStmtBlock(forInStmt.body, \"for in statement\");\n return forInStmt;\n }\n\n public typeCheckWhile(whileStmt: WhileStatement): WhileStatement {\n whileStmt.cond = this.typeCheck(whileStmt.cond);\n this.typeCheckCondExpr(whileStmt.cond);\n whileStmt.body = this.typeCheck(whileStmt.body);\n this.typeCheckCompoundStmtBlock(whileStmt.body, \"while statement\");\n whileStmt.type = this.voidType;\n return whileStmt;\n }\n\n public typeCheckDoWhile(doWhileStmt: DoWhileStatement): DoWhileStatement {\n doWhileStmt.cond = this.typeCheck(doWhileStmt.cond);\n this.typeCheckCondExpr(doWhileStmt.cond);\n doWhileStmt.body = this.typeCheck(doWhileStmt.body);\n this.typeCheckCompoundStmtBlock(doWhileStmt.body, \"do while statement\");\n doWhileStmt.type = this.voidType;\n return doWhileStmt;\n }\n\n public typeCheckCondExpr(cond: AST) {\n if (this.checker.styleSettings.assignmentInCond) {\n if ((cond !== null) &&\n (cond.nodeType >= NodeType.Asg) &&\n (cond.nodeType <= NodeType.LastAsg)) {\n this.checker.errorReporter.simpleError(cond, \"top-level assignment statement in conditional expression\");\n }\n }\n }\n\n public typeCheckCompoundStmtBlock(stmts: AST, stmtType: string) {\n if (this.checker.styleSettings.blockInCompoundStmt && stmts) {\n if (stmts.nodeType != NodeType.Block) {\n this.checker.errorReporter.styleError(stmts, stmtType + \" requires a block\");\n }\n }\n }\n public typeCheckIf(ifStmt: IfStatement): IfStatement {\n ifStmt.cond = this.typeCheck(ifStmt.cond);\n this.typeCheckCondExpr(ifStmt.cond);\n ifStmt.thenBod = this.typeCheck(ifStmt.thenBod);\n ifStmt.elseBod = this.typeCheck(ifStmt.elseBod);\n this.typeCheckCompoundStmtBlock(ifStmt.thenBod, \"if statement\");\n this.typeCheckCompoundStmtBlock(ifStmt.elseBod, \"if statement\");\n ifStmt.type = this.voidType;\n return ifStmt;\n }\n\n public typeFromAccessorFuncDecl(funcDecl: FuncDecl) {\n if (!funcDecl.isAccessor()) {\n return null;\n }\n\n if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n return funcDecl.type.call.signatures[0].returnType.type;\n }\n else {\n return funcDecl.type.call.signatures[0].parameters[0].getType();\n }\n }\n\n public typeCheckObjectLit(objectLit: UnaryExpression): void {\n\n var resultType = new Type();\n resultType.symbol = new TypeSymbol(this.checker.anon, objectLit.minChar,\n objectLit.limChar - objectLit.minChar,\n this.checker.locationInfo.unitIndex,\n resultType);\n\n resultType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n resultType.memberScope = new SymbolTableScope(resultType.members, null, null, null, null);\n\n var aggScope = new SymbolAggregateScope(resultType.symbol);\n aggScope.addParentScope(resultType.memberScope);\n aggScope.addParentScope(this.scope);\n resultType.containedScope = aggScope;\n var memberDecls = <ASTList>objectLit.operand;\n var prevThisType = this.thisType;\n var acceptTargetType = false;\n var targetType: Type = null;\n\n if (this.checker.hasTargetType()) {\n targetType = this.checker.getTargetTypeContext().contextualType;\n\n if (targetType && targetType.symbol && !this.checker.typeStatusIsFinished(targetType.symbol.typeCheckStatus)) {\n if (targetType.symbol.declAST) {\n this.typeCheck(targetType.symbol.declAST);\n }\n }\n acceptTargetType = true;\n }\n\n if (memberDecls) {\n for (var i = 0, len = memberDecls.members.length; i < len; i++) {\n\n var binex = <BinaryExpression>memberDecls.members[i];\n\n var id = binex.operand1;\n var text: string;\n var targetMember: Symbol = null;\n var fieldSymbol: FieldSymbol = null;\n\n if (id.nodeType == NodeType.Name) {\n text = (<Identifier>id).text;\n }\n else if (id.nodeType == NodeType.QString) {\n // TODO: set text to unescaped string\n var idText = (<StringLiteral>id).text;\n text = idText.substring(1, idText.length - 1);\n }\n else {\n this.checker.errorReporter.simpleError(objectLit,\n \"malformed object literal\");\n resultType = this.anyType;\n break;\n }\n\n if (acceptTargetType && targetType.memberScope) {\n targetMember = targetType.memberScope.find(text, false, false);\n }\n\n // before typechecking an accessor function member, we need to initialize its accessor symbol\n if (binex.operand2.nodeType == NodeType.FuncDecl && (<FuncDecl>binex.operand2).isAccessor()) {\n\n var funcDecl = <FuncDecl>binex.operand2;\n var accessorSym: FieldSymbol = resultType.members.publicMembers.lookup(text);\n\n accessorSym = this.checker.createAccessorSymbol(funcDecl, accessorSym, resultType, true, false, resultType.memberScope, null);\n funcDecl.accessorSymbol = accessorSym;\n fieldSymbol = accessorSym;\n if (id.nodeType == NodeType.Name) {\n (<Identifier>id).sym = accessorSym;\n }\n }\n\n this.checker.typeCheckWithContextualType(acceptTargetType && targetMember ? targetMember.getType() : null, false, acceptTargetType, binex.operand2);\n\n if (acceptTargetType && targetMember) {\n // Note that we accept 'any' in place of a valid subtype \n if ((binex.operand2.type == this.anyType || this.checker.sourceIsAssignableToTarget(binex.operand2.type, targetMember.getType())) ||\n (binex.operand2.nodeType == NodeType.FuncDecl &&\n (<FuncDecl>binex.operand2).isAccessor() &&\n this.typeFromAccessorFuncDecl(<FuncDecl>binex.operand2) == targetMember.getType())) {\n // set the field type to the proper contextual type\n // this is especially important in the 'any' case, so that\n // fields typed to 'any' aren't accepted for contextual typing,\n // but never properly set to the target type\n binex.operand1.type = targetMember.getType();\n }\n }\n else {\n // here we sub in 'any' for 'undefined' to account for field initialization to\n // 'undefined' \n binex.operand2.type = binex.operand2.type == this.checker.undefinedType ? this.anyType : binex.operand2.type;\n }\n\n // the field symbol hasn't been set by a getter or setter\n if (fieldSymbol == null) {\n var memberType = binex.operand2.type;\n var field = new ValueLocation();\n fieldSymbol =\n new FieldSymbol(text, id.minChar,\n this.checker.locationInfo.unitIndex,\n true, field);\n fieldSymbol.flags |= SymbolFlags.Property;\n field.symbol = fieldSymbol;\n fieldSymbol.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n field.typeLink = new TypeLink();\n field.typeLink.type = memberType;\n resultType.members.publicMembers.add(text, fieldSymbol);\n }\n fieldSymbol.isObjectLitField = true;\n }\n }\n\n this.thisType = prevThisType;\n objectLit.type = resultType;\n if (targetType) {\n objectLit.targetType = targetType;\n }\n }\n\n public typeCheckArrayLit(arrayLit: UnaryExpression): void {\n var elements = <ASTList>arrayLit.operand;\n var elementType = this.anyType;\n var targetElementType: Type = null;\n var comparisonInfo = new TypeComparisonInfo();\n comparisonInfo.onlyCaptureFirstError = true;\n\n // if the target type is an array type, extract the element type\n if (this.checker.hasTargetType()) {\n var targetType = this.checker.getTargetTypeContext().contextualType;\n if (targetType.elementType) {\n targetElementType = targetType.elementType;\n }\n }\n\n if (elements) {\n\n var prevInArrayElemTypeCheck = this.inArrayElementTypeCheck;\n\n this.inArrayElementTypeCheck = true;\n this.checker.typeCheckWithContextualType(targetElementType, this.checker.inProvisionalTypecheckMode(), targetElementType != null, elements);\n this.inArrayElementTypeCheck = prevInArrayElemTypeCheck;\n\n elementType = elements.members[0].type;\n\n var collection: ITypeCollection = {\n getLength: () => { return elements.members.length; },\n setTypeAtIndex: (index: number, type: Type) => { elements.members[index].type = type; },\n getTypeAtIndex: (index: number) => { return elements.members[index].type; }\n }\n\n elementType = this.checker.findBestCommonType(elementType, targetElementType, collection, false, comparisonInfo);\n\n // if the array type is the undefined type, we should widen it to any\n // if it's of the null type, only widen it if it's not in a nested array element, so as not to \n // short-circuit any checks for the best common type\n if (elementType == this.checker.undefinedType || (!prevInArrayElemTypeCheck && elementType == this.nullType)) {\n elementType = this.anyType;\n }\n }\n if (!elementType) {\n var emsg = \"Incompatible types in array literal expression\";\n if (!comparisonInfo.message) {\n this.checker.errorReporter.simpleError(arrayLit, emsg);\n }\n else {\n this.checker.errorReporter.simpleError(arrayLit, emsg + \": \" + comparisonInfo.message);\n }\n elementType = this.anyType;\n }\n else if (targetElementType) {\n // for the case of zero-length 'any' arrays, we still want to set the contextual type, if\n // need be\n if (this.checker.sourceIsAssignableToTarget(elementType, targetElementType)) {\n elementType = targetElementType;\n }\n }\n\n arrayLit.type = this.checker.makeArrayType(elementType);\n\n }\n\n public checkForVoidConstructor(type: Type, ast: AST) {\n if (type &&\n type.construct &&\n type.construct.signatures.length > 0) {\n\n for (var i = 0; i < type.construct.signatures.length; i++) {\n if (type.construct.signatures[i].returnType.type == this.checker.voidType) {\n this.checker.errorReporter.simpleError(ast, \"Constructors may not have a return type of 'void'\");\n break;\n }\n }\n }\n }\n\n // REVIEW: the code below could set the signature type of the function to the current return\n // type, which would have a benefit of reducing the risk of a recursive typecheck scenario, but is\n // is technically wrong - mergeOrdered will only work properly if the best common supertype\n // comes before any sibling types. This would mean that if a function, \"color()\", returned\n // three types (in order) - \"Red\", \"Blue\", and \"IColor\", an \"Incompatible return type\" error \n // would be triggered. However, if \"color()\" returned (in order) \"Red\", \"IColor\" and \"Blue\"\n // no error would be triggered, and the return type of the function would be \"IColor\"\n public typeCheckReturn(returnStmt: ReturnStatement): ReturnStatement {\n\n if (this.thisFnc) {\n var targetType: Type = null;\n\n // determine the target type\n if (this.checker.hasTargetType()) {\n var tcContext = this.checker.getTargetTypeContext();\n var accessorType = tcContext.targetAccessorType;\n\n if (accessorType) {\n targetType = accessorType;\n }\n else {\n var targetSig = this.checker.getTargetTypeContext().targetSig;\n if (targetSig && targetSig.returnType.type != this.voidType) {\n targetType = targetSig.returnType.type;\n }\n }\n }\n\n if (returnStmt.returnExpression) {\n this.thisFnc.fncFlags |= FncFlags.HasReturnExpression;\n\n if (targetType == null && this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type && this.thisFnc.returnTypeAnnotation.type != this.voidType) {\n targetType = this.thisFnc.returnTypeAnnotation.type;\n }\n\n this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), targetType != null, returnStmt.returnExpression);\n\n var expectedReturnType: Type =\n (this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type) ?\n this.thisFnc.returnTypeAnnotation.type :\n targetType;\n if (expectedReturnType) {\n if (expectedReturnType == this.voidType && returnStmt.returnExpression.type != this.voidType) {\n this.checker.errorReporter.simpleError(returnStmt,\n \"Return with value expression in void function\");\n\n // even though we've raised an error, use the more specific type\n returnStmt.type = returnStmt.returnExpression.type;\n }\n else {\n returnStmt.returnExpression = this.cast(returnStmt.returnExpression, expectedReturnType);\n returnStmt.type = expectedReturnType;\n }\n }\n else {\n if (targetType) {\n if (returnStmt.returnExpression.type != this.voidType) {\n returnStmt.returnExpression = this.cast(returnStmt.returnExpression, targetType);\n }\n else {\n returnStmt.returnExpression.type = targetType;\n }\n }\n returnStmt.type = returnStmt.returnExpression.type;\n }\n this.thisFnc.returnStatementsWithExpressions[this.thisFnc.returnStatementsWithExpressions.length] = returnStmt;\n }\n else {\n returnStmt.type = targetType == null ? this.checker.voidType : targetType; //((this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type) ? this.thisFnc.returnTypeAnnotation.type : this.checker.voidType) : targetType;\n }\n }\n\n return returnStmt;\n }\n\n public typeCheckInstOf(ast: AST): AST {\n var binex = <BinaryExpression>ast;\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n\n if (!((binex.operand1.type == this.checker.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand1.type, this.objectInterfaceType)) &&\n (binex.operand2.type == this.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand2.type, this.functionInterfaceType)))) {\n this.checker.errorReporter.simpleError(ast, \"The instanceof operator requires the left operand to be of type Any or an object type, and the right operand to be of type Any or a subtype of the Function interface type\");\n }\n binex.type = this.booleanType;\n return binex;\n }\n\n public typeCheckCommaOperator(ast: AST): AST {\n var binex = <BinaryExpression>ast;\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n binex.type = binex.operand2.type;\n return binex;\n }\n\n public typeCheckLogOr(binex: BinaryExpression): BinaryExpression {\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n var leftType = binex.operand1.type;\n var rightType = binex.operand2.type;\n\n if (leftType == this.checker.anyType || rightType == this.checker.anyType) {\n binex.type = this.checker.anyType;\n }\n else if (leftType == this.checker.booleanType) {\n if (rightType == this.checker.booleanType) {\n binex.type = this.checker.booleanType;\n }\n else {\n binex.type = this.checker.anyType;\n }\n }\n else if (leftType == this.checker.numberType) {\n if (rightType == this.checker.numberType) {\n binex.type = this.checker.numberType;\n }\n else {\n binex.type = this.checker.anyType;\n }\n }\n else if (leftType == this.checker.stringType) {\n if (rightType == this.checker.stringType) {\n binex.type = this.checker.stringType;\n }\n else {\n binex.type = this.checker.anyType;\n }\n }\n else {\n if (this.checker.sourceIsSubtypeOfTarget(leftType, rightType)) {\n binex.type = rightType;\n }\n else if (this.checker.sourceIsSubtypeOfTarget(rightType, leftType)) {\n binex.type = leftType;\n }\n else {\n binex.type = this.checker.anyType;\n }\n }\n return binex;\n }\n\n public typeCheckLogAnd(binex: BinaryExpression): BinaryExpression {\n binex.operand1 = this.typeCheck(binex.operand1);\n binex.operand2 = this.typeCheck(binex.operand2);\n binex.type = binex.operand2.type;\n return binex;\n }\n\n public tryAddCandidates(signature: Signature, actuals: Type[], exactCandidates: Signature[], conversionCandidates: Signature[], comparisonInfo: TypeComparisonInfo): void {\n var lowerBound = signature.nonOptionalParameterCount; // required parameters\n var upperBound = signature.parameters.length; // required and optional parameters\n var formalLen = lowerBound;\n var acceptable = false;\n\n if ((actuals.length >= lowerBound) && (signature.hasVariableArgList || actuals.length <= upperBound)) {\n formalLen = (signature.hasVariableArgList ? signature.parameters.length : actuals.length);\n acceptable = true;\n }\n\n var repeatType: Type = null;\n\n if (acceptable || signature.hasVariableArgList) {\n // assumed structure here is checked when signature is formed\n if (signature.hasVariableArgList) {\n formalLen -= 1;\n repeatType = (<ParameterSymbol>signature.parameters[formalLen]).parameter.typeLink.type;\n repeatType = repeatType.elementType;\n acceptable = actuals.length >= formalLen;\n }\n var len = actuals.length;\n\n var exact = acceptable;\n var convert = acceptable;\n for (var i = 0; i < len; i++) {\n var typeA: Type;\n if (i < formalLen) {\n typeA =\n (<ParameterSymbol>signature.parameters[i]).parameter.typeLink.type;\n }\n else {\n typeA = repeatType;\n }\n\n var typeB = actuals[i];\n if (!typeA || !typeB || !(this.checker.typesAreIdentical(typeA, typeB))) {\n exact = false;\n }\n // is the argument assignable to the parameter?\n if (!this.checker.sourceIsAssignableToTarget(typeB, typeA, comparisonInfo)) {\n convert = false;\n }\n if (!(exact || convert)) {\n break;\n }\n }\n if (exact) {\n exactCandidates[exactCandidates.length] = signature;\n }\n else if (convert && (exactCandidates.length == 0)) {\n conversionCandidates[conversionCandidates.length] = signature;\n }\n\n }\n }\n\n public resolveOverload(application: AST, group: SignatureGroup): Signature {\n var rd = this.resolutionDataCache.getResolutionData();\n var actuals = rd.actuals;\n var exactCandidates = rd.exactCandidates;\n var conversionCandidates = rd.conversionCandidates;\n var candidate: Signature = null;\n var hasOverloads = group.signatures.length > 1;\n var comparisonInfo = new TypeComparisonInfo();\n var args: ASTList = null;\n var target: AST = null;\n\n if (application.nodeType == NodeType.Call || application.nodeType == NodeType.New) {\n var callEx = <CallExpression>application;\n args = callEx.arguments;\n target = callEx.target;\n if (callEx.arguments) {\n var len = callEx.arguments.members.length;\n for (var i = 0; i < len; i++) {\n actuals[i] = callEx.arguments.members[i].type;\n }\n }\n }\n else if (application.nodeType == NodeType.Index) {\n var binExp = <BinaryExpression>application;\n target = binExp.operand1;\n args = new ASTList();\n args.members[0] = binExp.operand2;\n actuals[0] = binExp.operand2.type;\n }\n\n for (var j = 0, groupLen = group.signatures.length; j < groupLen; j++) {\n var signature = group.signatures[j];\n if (hasOverloads && signature == group.definitionSignature && !this.checker.canCallDefinitionSignature) {\n continue;\n }\n if (!signature.returnType.type && signature.declAST &&\n (signature.typeCheckStatus != TypeCheckStatus.Finished)) {\n this.typeCheckFunction(signature.declAST);\n }\n this.tryAddCandidates(signature, actuals, exactCandidates, conversionCandidates, comparisonInfo);\n }\n if (exactCandidates.length == 0) {\n\n var applicableCandidates = this.checker.getApplicableSignatures(conversionCandidates, args, comparisonInfo);\n if (applicableCandidates.length > 0) {\n var candidateInfo = this.checker.findMostApplicableSignature(applicableCandidates, args);\n if (candidateInfo.ambiguous) {\n this.checker.errorReporter.simpleError(target, \"Ambiguous call expression - could not choose overload\");\n }\n candidate = candidateInfo.sig;\n }\n else {\n var emsg = \"Supplied parameters do not match any signature of call target\";\n if (comparisonInfo.message) {\n this.checker.errorReporter.simpleError(target, emsg + \":\\n\\t\" + comparisonInfo.message);\n }\n else {\n this.checker.errorReporter.simpleError(target, emsg);\n }\n }\n }\n else {\n if (exactCandidates.length > 1) {\n var applicableSigs: ApplicableSignature[] = [];\n for (var i = 0; i < exactCandidates.length; i++) {\n applicableSigs[i] = { signature: exactCandidates[i], hadProvisionalErrors: false };\n }\n var candidateInfo = this.checker.findMostApplicableSignature(applicableSigs, args);\n if (candidateInfo.ambiguous) {\n this.checker.errorReporter.simpleError(target, \"Ambiguous call expression - could not choose overload\");\n }\n candidate = candidateInfo.sig;\n }\n else {\n candidate = exactCandidates[0];\n }\n }\n\n this.resolutionDataCache.returnResolutionData(rd);\n return candidate;\n }\n\n public typeCheckNew(ast: AST): AST {\n var callEx = <CallExpression>ast;\n\n callEx.target = this.typeCheck(callEx.target);\n var target = callEx.target;\n if (target.type.construct || target.type.call) {\n this.preTypeCheckCallArgs(callEx.arguments);\n }\n else {\n callEx.arguments = <ASTList>this.typeCheck(callEx.arguments);\n }\n\n if (target.type == this.anyType) {\n callEx.type = this.anyType;\n callEx.arguments = <ASTList>this.typeCheck(callEx.arguments);\n }\n else {\n if (target.type.construct) {\n var signature = this.resolveOverload(callEx, target.type.construct);\n if (signature == null) {\n callEx.type = this.anyType;\n }\n else if (signature.returnType.type == this.voidType) {\n callEx.type = this.anyType;\n callEx.signature = signature;\n }\n else {\n callEx.type = signature.returnType.type;\n callEx.signature = signature;\n }\n }\n else if (target.type.call) {\n var signature = this.resolveOverload(callEx, target.type.call);\n if (signature == null) {\n callEx.type = this.anyType;\n }\n else if ((signature.returnType.type == this.voidType) || (signature.returnType.type == this.anyType)) {\n callEx.type = this.anyType;\n callEx.signature = signature;\n }\n else {\n this.checker.errorReporter.simpleError(callEx.target,\n \"new expression only valid on constructors\");\n }\n }\n else if (target.type.elementType) {\n callEx.type = target.type;\n }\n else {\n this.checker.errorReporter.invalidCall(callEx, callEx.nodeType, this.scope);\n callEx.type = this.anyType;\n }\n }\n\n this.postTypeCheckCallArgs(callEx);\n\n return callEx;\n }\n\n // Typecheck all args that cannot be affected by contextual typing of overloads\n public preTypeCheckCallArgs(args: ASTList) {\n\n if (!args) {\n return;\n }\n\n for (var i = 0; i < args.members.length; i++) {\n switch (args.members[i].nodeType) {\n case NodeType.FuncDecl:\n case NodeType.ObjectLit:\n case NodeType.ArrayLit:\n continue;\n default:\n this.typeCheck(args.members[i]);\n break;\n }\n }\n }\n\n public postTypeCheckCallArgs(callEx: CallExpression) {\n\n var acceptedTargetType = false;\n var i = 0;\n\n if (callEx.target &&\n callEx.target.type &&\n callEx.signature &&\n callEx.arguments) {\n var sig = callEx.signature;\n\n if (sig && callEx.arguments.members.length >= sig.nonOptionalParameterCount) {\n acceptedTargetType = true;\n var targetType: Type = null;\n var nonVarArgFormalParamLength = sig.hasVariableArgList ? sig.parameters.length - 1 : sig.parameters.length;\n var nonVarArgActualParamLength = callEx.arguments.members.length < nonVarArgFormalParamLength ? callEx.arguments.members.length : nonVarArgFormalParamLength\n\n for (i = 0; i < nonVarArgActualParamLength; i++) {\n targetType = sig.parameters[i].getType();\n switch (callEx.arguments.members[i].nodeType) {\n case NodeType.FuncDecl:\n case NodeType.ObjectLit:\n case NodeType.ArrayLit:\n this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), !sig.parameters[i].declAST.isParenthesized, callEx.arguments.members[i]);\n break;\n }\n }\n\n if (sig.hasVariableArgList) {\n var varArgParamIndex = sig.nonOptionalParameterCount - 1;\n targetType = sig.parameters[varArgParamIndex].getType();\n if (targetType) {\n targetType = targetType.elementType;\n }\n var isParenthesized = !sig.parameters[varArgParamIndex].declAST.isParenthesized;\n for (i = nonVarArgActualParamLength; i < callEx.arguments.members.length; i++) {\n switch (callEx.arguments.members[i].nodeType) {\n case NodeType.FuncDecl:\n case NodeType.ObjectLit:\n case NodeType.ArrayLit:\n this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), isParenthesized, callEx.arguments.members[i]);\n break;\n }\n }\n }\n }\n }\n\n if (!acceptedTargetType && callEx.arguments) {\n this.checker.killCurrentContextualType();\n\n for (i = 0; i < callEx.arguments.members.length; i++) {\n switch (callEx.arguments.members[i].nodeType) {\n case NodeType.FuncDecl:\n case NodeType.ObjectLit:\n case NodeType.ArrayLit:\n this.typeCheck(callEx.arguments.members[i]);\n break;\n default:\n continue;\n }\n }\n }\n }\n\n public typeCheckCall(ast: AST): AST {\n var callEx = <CallExpression>ast;\n if (this.checker.styleSettings.newMustBeUsed && (ast.nodeType == NodeType.New)) {\n if (hasFlag(ast.flags, ASTFlags.IsStatement)) {\n this.checker.errorReporter.styleError(ast, \"use of new expression as a statement\");\n }\n }\n else if ((!this.checker.styleSettings.evalOK) && (ast.nodeType == NodeType.Call)) {\n if ((callEx.target.nodeType == NodeType.Name) && ((<Identifier>callEx.target).text == \"eval\")) {\n this.checker.errorReporter.styleError(callEx, \"eval not permitted\");\n }\n }\n\n if (callEx.target.nodeType == NodeType.FuncDecl) {\n (<FuncDecl>callEx.target).isInlineCallLiteral = true;\n }\n\n var prevInSuperCall = this.inSuperCall;\n\n if (callEx.target.nodeType == NodeType.Super) {\n this.inSuperCall = true;\n }\n\n callEx.target = this.typeCheck(callEx.target);\n this.preTypeCheckCallArgs(callEx.arguments);\n\n var target = callEx.target;\n\n if ((target.type == null) || (target.type == this.anyType) || (this.functionInterfaceType && target.type == this.functionInterfaceType)) {\n callEx.type = this.anyType;\n }\n else {\n var fnType = target.type;\n if (fnType.call) {\n var signature = this.resolveOverload(callEx, fnType.call);\n if (signature == null) {\n callEx.type = this.anyType;\n }\n else {\n callEx.type = signature.returnType.type;\n callEx.signature = signature;\n }\n }\n else {\n // track calls to class base class\n if (callEx.target.nodeType == NodeType.Super &&\n this.thisFnc &&\n this.thisFnc.isConstructor &&\n hasFlag(this.thisFnc.fncFlags, FncFlags.ClassMethod)) {\n\n // Need to use the class type for the construct signature, not the instance type\n var signature = fnType.symbol.type.construct ? this.resolveOverload(callEx, fnType.symbol.type.construct) : null;\n\n if (signature == null) {\n callEx.type = this.anyType;\n }\n else {\n callEx.flags |= ASTFlags.ClassBaseConstructorCall;\n callEx.type = signature.returnType.type;\n callEx.signature = signature;\n }\n }\n else {\n callEx.type = this.anyType;\n this.checker.errorReporter.invalidCall(callEx, callEx.nodeType, this.scope);\n }\n }\n }\n this.postTypeCheckCallArgs(callEx);\n\n this.inSuperCall = prevInSuperCall;\n\n return callEx;\n }\n\n public assignScopes(ast: AST) {\n var script = <Script>ast;\n this.checker.locationInfo = script.locationInfo;\n var globalChain = new ScopeChain(this.checker.gloMod, null, this.globalScope);\n var context = new AssignScopeContext(globalChain, this, [this.checker.currentModDecl]);\n getAstWalkerFactory().walk(ast, preAssignScopes, postAssignScopes, null, context);\n }\n\n public findMemberScope(enclosingScopeContext: EnclosingScopeContext, matchFlag: ASTFlags) {\n var enclosingScope = enclosingScopeContext.getScope();\n var pos = enclosingScopeContext.pos - enclosingScopeContext.getScriptFragmentPosition();\n var scriptFragment = enclosingScopeContext.getScriptFragment();\n\n var memContext = new MemberScopeContext(this, pos, matchFlag);\n memContext.scope = enclosingScope;\n if (scriptFragment.nodeType == NodeType.Name) {\n return scriptFragment.type.getMemberScope(this);\n }\n else {\n getAstWalkerFactory().walk(scriptFragment, preFindMemberScope, null, null, memContext);\n if (memContext.ast && enclosingScopeContext.enclosingClassDecl && memContext.ast.type == enclosingScopeContext.enclosingClassDecl.type.instanceType) {\n enclosingScopeContext.publicsOnly = false;\n }\n if (memContext.type) {\n return memContext.type.getMemberScope(this);\n }\n else {\n return null;\n }\n }\n }\n\n public findMemberScopeAt(enclosingScopeContext: EnclosingScopeContext) {\n return this.findMemberScope(enclosingScopeContext, ASTFlags.DotLHS);\n }\n\n public findMemberScopeAtFullAst(enclosingScopeContext: EnclosingScopeContext) {\n var matchFlag = ASTFlags.DotLHS;\n var pos = enclosingScopeContext.pos;\n var astResult: AST = null;\n\n var preFindMemberScopeFullAst = function (ast: AST, parent: AST, walker: IAstWalker) {\n if (isValidAstNode(ast)) {\n // Note: pos == ast.limChar in case of incomplete code (e.g. \"foo.\")\n // Note: (pos - 1) == ast.limChar in case of complete code (e.g. \"foo.bar\")\n if (hasFlag(ast.flags, matchFlag) && (pos == ast.limChar || (pos - 1) == ast.limChar)) {\n astResult = ast;\n walker.options.stopWalk();\n }\n\n // Stop traversal if range does not contain position\n walker.options.goChildren = (ast.minChar <= pos) && (pos <= ast.limChar);\n }\n return ast;\n }\n\n var preFindMemberScopeFullAstFuzy = function (ast: AST, parent: AST, walker: IAstWalker) {\n if (isValidAstNode(ast)) {\n if (hasFlag(ast.flags, matchFlag) && ((ast.minChar < pos) && (pos <= ast.limChar))) {\n astResult = ast;\n }\n\n // Stop traversal if range does not contain position\n walker.options.goChildren = (ast.minChar <= pos) && (pos <= ast.limChar);\n }\n return ast;\n }\n\n getAstWalkerFactory().walk(enclosingScopeContext.script, preFindMemberScopeFullAst);\n\n if (astResult == null) {\n // Perform a more \"fusy\" match. This is because the limChar of AST nodes is sometimes\n // not what we expect, for example:\n // foo./*comment*/;\n // In this case, limChar points to \";\" instead of \".\" (because of the trailing comment).\n getAstWalkerFactory().walk(enclosingScopeContext.script, preFindMemberScopeFullAstFuzy);\n }\n\n if (astResult &&\n enclosingScopeContext.enclosingClassDecl &&\n astResult.type == enclosingScopeContext.enclosingClassDecl.type.instanceType) {\n enclosingScopeContext.publicsOnly = false;\n }\n\n if (astResult && astResult.type) {\n return astResult.type.getMemberScope(this);\n }\n else {\n return null;\n }\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///<reference path='diagnostics.ts' />\n///<reference path='flags.ts' />\n///<reference path='nodeTypes.ts' />\n///<reference path='hashTable.ts' />\n///<reference path='ast.ts' />\n///<reference path='astWalker.ts' />\n///<reference path='astWalkerCallback.ts' />\n///<reference path='astPath.ts' />\n///<reference path='astLogger.ts' />\n///<reference path='binder.ts' />\n///<reference path='base64.ts' />\n///<reference path='sourceMapping.ts' />\n///<reference path='emitter.ts' />\n///<reference path='errorReporter.ts' />\n///<reference path='parser.ts' />\n///<reference path='printContext.ts' />\n///<reference path='scanner.ts' />\n///<reference path='scopeAssignment.ts' />\n///<reference path='scopeWalk.ts' />\n///<reference path='signatures.ts' />\n///<reference path='symbols.ts' />\n///<reference path='symbolScope.ts' />\n///<reference path='tokens.ts' />\n///<reference path='typeChecker.ts' />\n///<reference path='typeCollection.ts' />\n///<reference path='typeFlow.ts' />\n///<reference path='types.ts' />\n///<reference path='pathUtils.ts' />\n///<reference path='referenceResolution.ts' />\n///<reference path='precompile.ts' />\n///<reference path='incrementalParser.ts' />\n///<reference path='declarationEmitter.ts' />\n\nmodule TypeScript {\n\n export enum UpdateUnitKind {\n Unknown,\n NoEdits,\n EditsInsideSingleScope,\n }\n\n export class ScriptEditRange {\n constructor (public minChar: number,\n public limChar: number,\n public delta: number) { }\n\n static unknown(): ScriptEditRange {\n return new ScriptEditRange(-1, -1, -1);\n }\n\n public isUnknown() {\n return this.minChar === -1 && this.limChar === -1 && this.delta === -1;\n }\n\n public containsPosition(pos: number) {\n return (this.minChar <= pos && pos < this.limChar)\n || (this.minChar <= pos && pos < this.limChar + this.delta);\n }\n\n public toString(): string {\n return \"editRange(minChar=\" + this.minChar + \", limChar=\" + this.limChar + \", delta=\" + this.delta + \")\";\n }\n }\n\n export class UpdateUnitResult {\n\n constructor (public kind: UpdateUnitKind, public unitIndex: number, public script1: Script, public script2: Script) { }\n\n public scope1: AST = null;\n public scope2: AST = null;\n public editRange: ScriptEditRange = null;\n public parseErrors: ErrorEntry[] = [];\n\n static noEdits(unitIndex: number) {\n return new UpdateUnitResult(UpdateUnitKind.NoEdits, unitIndex, null, null);\n }\n\n static unknownEdits(script1: Script, script2: Script, parseErrors: ErrorEntry[]) {\n var result = new UpdateUnitResult(UpdateUnitKind.Unknown, script1.locationInfo.unitIndex, script1, script2);\n result.parseErrors = parseErrors;\n return result;\n }\n\n static singleScopeEdits(script1: Script, script2: Script, scope1: AST, scope2: AST, editRange: ScriptEditRange, parseErrors: ErrorEntry[]) {\n var result = new UpdateUnitResult(UpdateUnitKind.EditsInsideSingleScope, script1.locationInfo.unitIndex, script1, script2);\n result.scope1 = scope1;\n result.scope2 = scope2;\n result.editRange = editRange;\n result.parseErrors = parseErrors;\n return result;\n }\n }\n\n export class ErrorEntry {\n constructor (public unitIndex: number,\n public minChar: number,\n public limChar: number,\n public message: string) { }\n }\n\n export var defaultSettings = new CompilationSettings();\n\n export interface EmitterIOHost {\n // function that can even create a folder structure if needed\n createFile(path: string, useUTF8?: bool): ITextWriter;\n\n // function to check if file exists on the disk\n fileExists(path: string): bool;\n\n // Function to check if the directory exists on the disk\n directoryExists(path: string): bool;\n\n // Resolves the path\n resolvePath(path: string): string;\n }\n\n export class TypeScriptCompiler {\n public parser = new Parser();\n public typeChecker: TypeChecker;\n public typeFlow: TypeFlow = null;\n public scripts = new ASTList();\n public units: LocationInfo[] = new LocationInfo[];\n public errorReporter: ErrorReporter;\n\n public persistentTypeState: PersistentGlobalTypeState;\n\n\n public emitSettings: EmitOptions;\n\n constructor (public errorOutput: ITextWriter, public logger: ILogger = new NullLogger(), public settings: CompilationSettings = defaultSettings) {\n this.errorReporter = new ErrorReporter(this.errorOutput);\n this.persistentTypeState = new PersistentGlobalTypeState(this.errorReporter);\n this.errorReporter.parser = this.parser;\n this.initTypeChecker(this.errorOutput);\n\n this.parser.style_requireSemi = this.settings.styleSettings.requireSemi;\n this.parser.style_funcInLoop = this.settings.styleSettings.funcInLoop;\n this.parser.inferPropertiesFromThisAssignment = this.settings.inferPropertiesFromThisAssignment;\n this.emitSettings = new EmitOptions(this.settings);\n codeGenTarget = settings.codeGenTarget;\n }\n\n public timeFunction(funcDescription: string, func: () => any): any {\n return TypeScript.timeFunction(this.logger, funcDescription, func);\n }\n\n public initTypeChecker(errorOutput: ITextWriter) {\n // The initial \"refresh\" initializes the persistent type state\n this.persistentTypeState.refreshPersistentState();\n this.typeChecker = new TypeChecker(this.persistentTypeState);\n this.typeChecker.errorReporter = this.errorReporter;\n\n // REVIEW: These properties should be moved out of the typeCheck object\n // ideally, CF should be a separate pass, independent of control flow\n this.typeChecker.checkControlFlow = this.settings.controlFlow;\n this.typeChecker.checkControlFlowUseDef = this.settings.controlFlowUseDef;\n this.typeChecker.printControlFlowGraph = this.settings.printControlFlow;\n\n this.typeChecker.errorsOnWith = this.settings.errorOnWith;\n this.typeChecker.styleSettings = this.settings.styleSettings;\n this.typeChecker.canCallDefinitionSignature = this.settings.canCallDefinitionSignature;\n\n this.errorReporter.checker = this.typeChecker;\n this.setErrorOutput(this.errorOutput);\n }\n\n public setErrorOutput(outerr) {\n this.errorOutput = outerr;\n this.errorReporter.setErrOut(outerr);\n this.parser.outfile = outerr;\n }\n\n public emitCommentsToOutput() {\n this.emitSettings = new EmitOptions(this.settings);\n }\n\n public setErrorCallback(fn: (minChar: number, charLen: number, message: string,\n unitIndex: number) =>void ) {\n this.parser.errorCallback = fn;\n }\n\n public updateUnit(prog: string, filename: string, setRecovery: bool) {\n return this.updateSourceUnit(new StringSourceText(prog), filename, setRecovery);\n }\n\n public updateSourceUnit(sourceText: ISourceText, filename: string, setRecovery: bool): bool {\n return this.timeFunction(\"updateSourceUnit(\" + filename + \")\", () => {\n var updateResult = this.partialUpdateUnit(sourceText, filename, setRecovery);\n return this.applyUpdateResult(updateResult);\n });\n }\n\n // Apply changes to compiler state.\n // Return \"false\" if the change is empty and nothing was updated.\n public applyUpdateResult(updateResult: UpdateUnitResult): bool {\n switch (updateResult.kind) {\n case UpdateUnitKind.NoEdits:\n return false;\n\n case UpdateUnitKind.Unknown:\n this.scripts.members[updateResult.unitIndex] = updateResult.script2;\n this.units[updateResult.unitIndex] = updateResult.script2.locationInfo;\n for (var i = 0, len = updateResult.parseErrors.length; i < len; i++) {\n var e = updateResult.parseErrors[i];\n if (this.parser.errorCallback) {\n this.parser.errorCallback(e.minChar, e.limChar - e.minChar, e.message, e.unitIndex);\n }\n }\n return true;\n\n case UpdateUnitKind.EditsInsideSingleScope:\n new IncrementalParser(this.logger).mergeTrees(updateResult);\n return true;\n }\n }\n\n public partialUpdateUnit(sourceText: ISourceText, filename: string, setRecovery: bool): UpdateUnitResult {\n return this.timeFunction(\"partialUpdateUnit(\" + filename + \")\", () => {\n for (var i = 0, len = this.units.length; i < len; i++) {\n if (this.units[i].filename == filename) {\n if ((<Script>this.scripts.members[i]).isResident) {\n return UpdateUnitResult.noEdits(i);\n }\n\n if (setRecovery) {\n this.parser.setErrorRecovery(null);\n }\n\n var updateResult: UpdateUnitResult;\n\n // Capture parsing errors so that they are part of \"updateResult\"\n var parseErrors: ErrorEntry[] = [];\n var errorCapture = (minChar: number, charLen: number, message: string, unitIndex: number): void => {\n parseErrors.push(new ErrorEntry(unitIndex, minChar, minChar + charLen, message));\n };\n var svErrorCallback = this.parser.errorCallback;\n if (svErrorCallback)\n this.parser.errorCallback = errorCapture;\n\n var oldScript = <Script>this.scripts.members[i];\n var newScript = this.parser.parse(sourceText, filename, i);\n\n if (svErrorCallback)\n this.parser.errorCallback = svErrorCallback;\n\n updateResult = UpdateUnitResult.unknownEdits(oldScript, newScript, parseErrors);\n\n return updateResult;\n }\n }\n throw new Error(\"Unknown file \\\"\" + filename + \"\\\"\");\n });\n }\n\n public addUnit(prog: string, filename: string, keepResident? = false, referencedFiles?: IFileReference[] = []): Script {\n return this.addSourceUnit(new StringSourceText(prog), filename, keepResident, referencedFiles);\n }\n\n public addSourceUnit(sourceText: ISourceText, filename: string, keepResident:bool, referencedFiles?: IFileReference[] = []): Script {\n return this.timeFunction(\"addSourceUnit(\" + filename + \", \" + keepResident + \")\", () => {\n var script: Script = this.parser.parse(sourceText, filename, this.units.length, AllowedElements.Global);\n script.referencedFiles = referencedFiles;\n script.isResident = keepResident;\n this.persistentTypeState.setCollectionMode(keepResident ? TypeCheckCollectionMode.Resident : TypeCheckCollectionMode.Transient);\n var index = this.units.length;\n this.units[index] = script.locationInfo;\n this.typeChecker.collectTypes(script);\n this.scripts.append(script);\n return script\n });\n }\n\n public parseUnit(prog: string, filename: string) {\n return this.parseSourceUnit(new StringSourceText(prog), filename);\n }\n\n public parseSourceUnit(sourceText: ISourceText, filename: string) {\n this.parser.setErrorRecovery(this.errorOutput);\n var script: Script = this.parser.parse(sourceText, filename, 0);\n\n var index = this.units.length;\n this.units[index] = script.locationInfo;\n this.typeChecker.collectTypes(script);\n this.scripts.append(script);\n }\n\n public typeCheck() {\n return this.timeFunction(\"typeCheck()\", () => {\n var binder = new Binder(this.typeChecker);\n this.typeChecker.units = this.units;\n binder.bind(this.typeChecker.globalScope, this.typeChecker.globals);\n binder.bind(this.typeChecker.globalScope, this.typeChecker.ambientGlobals);\n binder.bind(this.typeChecker.globalScope, this.typeChecker.globalTypes);\n binder.bind(this.typeChecker.globalScope, this.typeChecker.ambientGlobalTypes);\n this.typeFlow = new TypeFlow(this.logger, this.typeChecker.globalScope, this.parser, this.typeChecker);\n var i = 0;\n var script: Script = null;\n var len = this.scripts.members.length;\n\n\n this.persistentTypeState.setCollectionMode(TypeCheckCollectionMode.Resident);\n // first, typecheck resident \"lib\" scripts, if necessary\n for (i = 0; i < len; i++) {\n script = <Script>this.scripts.members[i];\n if (!script.isResident || script.hasBeenTypeChecked) { continue; }\n\n this.typeFlow.assignScopes(script);\n this.typeFlow.initLibs();\n }\n for (i = 0; i < len; i++) {\n script = <Script>this.scripts.members[i];\n if (!script.isResident || script.hasBeenTypeChecked) { continue; }\n\n this.typeFlow.typeCheck(script);\n script.hasBeenTypeChecked = true;\n }\n\n // next typecheck scripts that may change\n this.persistentTypeState.setCollectionMode(TypeCheckCollectionMode.Transient);\n len = this.scripts.members.length;\n for (i = 0; i < len; i++) {\n script = <Script>this.scripts.members[i];\n if (script.isResident) { continue; }\n this.typeFlow.assignScopes(script);\n this.typeFlow.initLibs();\n }\n for (i = 0; i < len; i++) {\n script = <Script>this.scripts.members[i];\n if (script.isResident) { continue; }\n this.typeFlow.typeCheck(script);\n }\n\n return null;\n });\n }\n\n public cleanASTTypesForReTypeCheck(ast: AST) {\n function cleanASTType(ast: AST, parent: AST): AST {\n ast.type = null;\n if (ast.nodeType == NodeType.VarDecl) {\n var vardecl = <VarDecl>ast;\n vardecl.sym = null;\n }\n else if (ast.nodeType == NodeType.ArgDecl) {\n var argdecl = <ArgDecl>ast;\n argdecl.sym = null;\n }\n else if (ast.nodeType == NodeType.Name) {\n var name = <Identifier>ast;\n name.sym = null;\n }\n else if (ast.nodeType == NodeType.FuncDecl) {\n var funcdecl = <FuncDecl>ast;\n funcdecl.signature = null;\n funcdecl.freeVariables = new Symbol[]\n funcdecl.symbols = null;\n funcdecl.accessorSymbol = null;\n funcdecl.scopeType = null;\n }\n else if (ast.nodeType == NodeType.ModuleDeclaration) {\n var modDecl = <ModuleDeclaration>ast;\n modDecl.mod = null;\n }\n else if (ast.nodeType == NodeType.With) {\n (<WithStatement>ast).withSym = null;\n }\n else if (ast.nodeType == NodeType.Catch) {\n (<Catch>ast).containedScope = null;\n }\n return ast;\n }\n TypeScript.getAstWalkerFactory().walk(ast, cleanASTType);\n }\n\n public cleanTypesForReTypeCheck() {\n return this.timeFunction(\"cleanTypesForReTypeCheck()\", () => {\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = this.scripts.members[i];\n if ((<Script>script).isResident) {\n continue;\n }\n this.cleanASTTypesForReTypeCheck(script);\n this.typeChecker.collectTypes(script);\n }\n\n return null;\n });\n }\n\n // Return \"true\" if the incremental typecheck was successful\n // Return \"false\" if incremental typecheck failed, requiring a full typecheck\n public attemptIncrementalTypeCheck(updateResult: TypeScript.UpdateUnitResult): bool {\n return this.timeFunction(\"attemptIncrementalTypeCheck()\", () => {\n // updateResult.kind == editsInsideFunction\n // updateResult.scope1 == old function\n // updateResult.scope2 == new function\n //REVIEW: What about typecheck errors? How do we replace the old ones with the new ones?\n return false;\n });\n }\n\n public reTypeCheck() {\n return this.timeFunction(\"reTypeCheck()\", () => {\n CompilerDiagnostics.analysisPass++;\n this.initTypeChecker(this.errorOutput);\n this.persistentTypeState.setCollectionMode(TypeCheckCollectionMode.Transient);\n this.cleanTypesForReTypeCheck();\n return this.typeCheck();\n });\n }\n\n private isDynamicModuleCompilation() {\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = <Script>this.scripts.members[i];\n if (!script.isDeclareFile && script.topLevelMod != null) {\n return true;\n }\n }\n return false;\n }\n\n private updateCommonDirectoryPath() {\n var commonComponents: string[] = [];\n var commonComponentsLength = -1;\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = <Script>this.scripts.members[i];\n if (script.emitRequired(this.emitSettings)) {\n var fileName = script.locationInfo.filename;\n var fileComponents = filePathComponents(fileName);\n if (commonComponentsLength == -1) {\n // First time at finding common path\n // So common path = directory of file\n commonComponents = fileComponents;\n commonComponentsLength = commonComponents.length;\n } else {\n var updatedPath = false;\n for (var j = 0; j < commonComponentsLength && j < fileComponents.length; j++) {\n if (commonComponents[j] != fileComponents[j]) {\n // The new components = 0 ... j -1\n commonComponentsLength = j;\n updatedPath = true;\n\n if (j == 0) {\n // Its error to not have common path\n this.errorReporter.emitterError(null, \"Cannot find the common subdirectory path for the input files\");\n return;\n }\n\n break;\n }\n }\n\n // If the fileComponent path completely matched and less than already found update the length\n if (!updatedPath && fileComponents.length < commonComponentsLength) {\n commonComponentsLength = fileComponents.length;\n }\n }\n }\n }\n\n this.emitSettings.commonDirectoryPath = commonComponents.slice(0, commonComponentsLength).join(\"/\") + \"/\";\n if (this.emitSettings.outputOption.charAt(this.emitSettings.outputOption.length - 1) != \"/\") {\n this.emitSettings.outputOption += \"/\";\n }\n }\n\n public parseEmitOption(ioHost: EmitterIOHost) {\n this.emitSettings.ioHost = ioHost;\n if (this.emitSettings.outputOption == \"\") {\n this.emitSettings.outputMany = true;\n this.emitSettings.commonDirectoryPath = \"\";\n return;\n }\n\n this.emitSettings.outputOption = switchToForwardSlashes(this.emitSettings.ioHost.resolvePath(this.emitSettings.outputOption));\n\n // Determine if output options is directory or file\n if (this.emitSettings.ioHost.directoryExists(this.emitSettings.outputOption)) {\n // Existing directory\n this.emitSettings.outputMany = true;\n } else if (this.emitSettings.ioHost.fileExists(this.emitSettings.outputOption)) {\n // Existing file\n this.emitSettings.outputMany = false;\n }\n else {\n // New File/directory\n this.emitSettings.outputMany = !isJSFile(this.emitSettings.outputOption);\n }\n\n // Verify if options are correct\n if (this.isDynamicModuleCompilation() && !this.emitSettings.outputMany) {\n this.errorReporter.emitterError(null, \"Cannot compile dynamic modules when emitting into single file\");\n }\n\n // Parse the directory structure\n if (this.emitSettings.outputMany) {\n this.updateCommonDirectoryPath();\n }\n }\n\n public useUTF8ForFile(script: Script) {\n if (this.emitSettings.outputMany) {\n return this.outputScriptToUTF8(script);\n } else {\n return this.outputScriptsToUTF8(<Script[]>(this.scripts.members));\n }\n }\n\n static mapToDTSFileName(fileName: string, wholeFileNameReplaced: bool) {\n return getDeclareFilePath(fileName);\n }\n\n private canEmitDeclarations(script?: Script) {\n if (!this.settings.generateDeclarationFiles) {\n return false;\n }\n\n // If its already a declare file or is resident or does not contain body \n if (!!script && (script.isDeclareFile || script.isResident || script.bod == null)) {\n return false;\n }\n\n return true;\n }\n\n public emitDeclarationsUnit(script: Script, reuseEmitter?: bool, declarationEmitter?: DeclarationEmitter) {\n if (!this.canEmitDeclarations(script)) {\n return null;\n }\n\n if (!declarationEmitter) {\n var declareFileName = this.emitSettings.mapOutputFileName(script.locationInfo.filename, TypeScriptCompiler.mapToDTSFileName);\n var declareFile = this.createFile(declareFileName, this.useUTF8ForFile(script));\n declarationEmitter = new DeclarationEmitter(this.typeChecker, this.emitSettings, this.errorReporter);\n declarationEmitter.setDeclarationFile(declareFile);\n }\n\n declarationEmitter.emitDeclarations(script);\n\n if (!reuseEmitter) {\n declarationEmitter.Close();\n return null;\n } else {\n return declarationEmitter;\n }\n }\n\n public emitDeclarations() {\n if (!this.canEmitDeclarations()) {\n return;\n }\n\n if (this.errorReporter.hasErrors) {\n // There were errors reported, do not generate declaration file\n return;\n }\n\n if (this.scripts.members.length == 0) {\n return;\n }\n\n var declarationEmitter: DeclarationEmitter = null;\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = <Script>this.scripts.members[i];\n if (this.emitSettings.outputMany || declarationEmitter == null) {\n // Create or reuse file\n declarationEmitter = this.emitDeclarationsUnit(script, !this.emitSettings.outputMany);\n } else {\n // Emit in existing emitter\n this.emitDeclarationsUnit(script, true, declarationEmitter);\n }\n }\n\n if (declarationEmitter) {\n declarationEmitter.Close();\n }\n }\n\n static mapToFileNameExtension(extension: string, fileName: string, wholeFileNameReplaced: bool) {\n if (wholeFileNameReplaced) {\n // The complete output is redirected in this file so do not change extension\n return fileName;\n } else {\n // Change the extension of the file\n var splitFname = fileName.split(\".\");\n splitFname.pop();\n return splitFname.join(\".\") + extension;\n }\n }\n\n static mapToJSFileName(fileName: string, wholeFileNameReplaced: bool) {\n return TypeScriptCompiler.mapToFileNameExtension(\".js\", fileName, wholeFileNameReplaced);\n }\n\n public emitUnit(script: Script, reuseEmitter?: bool, emitter?: Emitter) {\n if (!script.emitRequired(this.emitSettings)) {\n return null;\n }\n\n var fname = script.locationInfo.filename;\n if (!emitter) {\n var outFname = this.emitSettings.mapOutputFileName(fname, TypeScriptCompiler.mapToJSFileName);\n var outFile = this.createFile(outFname, this.useUTF8ForFile(script));\n emitter = new Emitter(this.typeChecker, outFname, outFile, this.emitSettings, this.errorReporter);\n if (this.settings.mapSourceFiles) {\n emitter.setSourceMappings(new TypeScript.SourceMapper(fname, outFname, outFile, this.createFile(outFname + SourceMapper.MapFileExtension, false), this.errorReporter));\n }\n } else if (this.settings.mapSourceFiles) {\n emitter.setSourceMappings(new TypeScript.SourceMapper(fname, emitter.emittingFileName, emitter.outfile, emitter.sourceMapper.sourceMapOut, this.errorReporter));\n }\n\n this.typeChecker.locationInfo = script.locationInfo;\n emitter.emitJavascript(script, TokenID.Comma, false);\n if (!reuseEmitter) {\n emitter.Close();\n return null;\n } else {\n return emitter;\n }\n }\n\n public emit(ioHost: EmitterIOHost) {\n this.parseEmitOption(ioHost);\n\n var emitter: Emitter = null;\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = <Script>this.scripts.members[i];\n if (this.emitSettings.outputMany || emitter == null) {\n emitter = this.emitUnit(script, !this.emitSettings.outputMany);\n } else {\n this.emitUnit(script, true, emitter);\n }\n }\n\n if (emitter) {\n emitter.Close();\n }\n }\n\n public emitToOutfile(outputFile: ITextWriter) {\n if (this.settings.mapSourceFiles) {\n throw Error(\"Cannot generate source map\");\n }\n\n if (this.settings.generateDeclarationFiles) {\n throw Error(\"Cannot generate declaration files\");\n }\n\n if (this.settings.outputOption != \"\") {\n throw Error(\"Cannot parse output option\");\n }\n\n var emitter: Emitter = emitter = new Emitter(this.typeChecker, \"stdout\", outputFile, this.emitSettings, this.errorReporter);;\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = <Script>this.scripts.members[i];\n this.typeChecker.locationInfo = script.locationInfo;\n emitter.emitJavascript(script, TokenID.Comma, false);\n }\n }\n\n public emitAST(ioHost: EmitterIOHost) {\n this.parseEmitOption(ioHost);\n\n var outFile: ITextWriter = null;\n var context: PrintContext = null;\n\n for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n var script = <Script>this.scripts.members[i];\n if (this.emitSettings.outputMany || context == null) {\n var fname = this.units[i].filename;\n var mapToTxtFileName = (fileName: string, wholeFileNameReplaced: bool) => {\n return TypeScriptCompiler.mapToFileNameExtension(\".txt\", fileName, wholeFileNameReplaced);\n };\n var outFname = this.emitSettings.mapOutputFileName(fname, mapToTxtFileName);\n outFile = this.createFile(outFname, this.useUTF8ForFile(script));\n context = new PrintContext(outFile, this.parser);\n }\n getAstWalkerFactory().walk(script, prePrintAST, postPrintAST, null, context);\n if (this.emitSettings.outputMany) {\n try {\n outFile.Close();\n } catch (e) {\n this.errorReporter.emitterError(null, e.message);\n }\n }\n }\n\n if (!this.emitSettings.outputMany) {\n try {\n outFile.Close();\n } catch (e) {\n this.errorReporter.emitterError(null, e.message);\n }\n }\n }\n\n private outputScriptToUTF8(script: Script): bool {\n return script.containsUnicodeChar || (this.emitSettings.emitComments && script.containsUnicodeCharInComment);\n }\n\n private outputScriptsToUTF8(scripts: Script[]): bool {\n for (var i = 0, len = scripts.length; i < len; i++) {\n var script = scripts[i];\n if (this.outputScriptToUTF8(script)) {\n return true;\n }\n }\n return false;\n }\n\n private createFile(fileName: string, useUTF8: bool): ITextWriter {\n try {\n // Creating files can cause exceptions, report them. \n return this.emitSettings.ioHost.createFile(fileName, useUTF8);\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n }\n\n export class ScopeEntry {\n constructor (\n public name: string,\n public type: string,\n public sym: Symbol) {\n }\n }\n\n export class ScopeTraversal {\n constructor (private compiler: TypeScriptCompiler) {\n }\n\n public getScope(enclosingScopeContext: EnclosingScopeContext): SymbolScope {\n if (enclosingScopeContext.enclosingObjectLit && enclosingScopeContext.isMemberCompletion) {\n return enclosingScopeContext.getObjectLiteralScope();\n }\n else if (enclosingScopeContext.isMemberCompletion) {\n if (enclosingScopeContext.useFullAst) {\n return this.compiler.typeFlow.findMemberScopeAtFullAst(enclosingScopeContext)\n }\n else {\n return this.compiler.typeFlow.findMemberScopeAt(enclosingScopeContext)\n }\n }\n else {\n return enclosingScopeContext.getScope();\n }\n }\n\n public getScopeEntries(enclosingScopeContext: EnclosingScopeContext): ScopeEntry[] {\n var scope = this.getScope(enclosingScopeContext);\n if (scope == null) {\n return [];\n }\n\n var inScopeNames: IHashTable = new StringHashTable();\n var allSymbolNames: string[] = scope.getAllSymbolNames(enclosingScopeContext.isMemberCompletion);\n\n // there may be duplicates between the type and value tables, so batch the symbols\n // getTypeNamesForNames will prefer the entry in the value table\n for (var i = 0; i < allSymbolNames.length; i++) {\n var name = allSymbolNames[i];\n\n // Skip global/internal symbols that won't compile in user code\n if (name == globalId || name == \"_Core\" || name == \"_element\") {\n continue;\n }\n\n inScopeNames.add(name, \"\");\n }\n\n var svModuleDecl = this.compiler.typeChecker.currentModDecl;\n this.compiler.typeChecker.currentModDecl = enclosingScopeContext.deepestModuleDecl;\n\n var result = this.getTypeNamesForNames(enclosingScopeContext, inScopeNames.getAllKeys(), scope);\n\n this.compiler.typeChecker.currentModDecl = svModuleDecl;\n return result;\n }\n\n private getTypeNamesForNames(enclosingScopeContext: EnclosingScopeContext, allNames: string[], scope: SymbolScope): ScopeEntry[] {\n var result: ScopeEntry[] = [];\n\n var enclosingScope = enclosingScopeContext.getScope();\n for (var i = 0; i < allNames.length; i++) {\n var name = allNames[i];\n // Search for the id in the value space first\n // if we don't find it, search in the type space.\n // We don't want to search twice, because the first\n // search may insert the name in the symbol value table\n // if the scope is aggregate\n var publicsOnly = enclosingScopeContext.publicsOnly && enclosingScopeContext.isMemberCompletion;\n var symbol = scope.find(name, publicsOnly, false/*typespace*/); // REVIEW: Should search public members only?\n if (symbol == null) {\n symbol = scope.find(name, publicsOnly, true/*typespace*/);\n }\n\n var displayThisMember = symbol && symbol.flags & SymbolFlags.Private ? symbol.container == scope.container : true;\n\n if (symbol) {\n // Do not add dynamic module names to the list, since they're not legal as identifiers\n if (displayThisMember && !isQuoted(symbol.name) && !isRelative(symbol.name)) {\n var typeName = symbol.getType().getScopedTypeName(enclosingScope);\n result.push(new ScopeEntry(name, typeName, symbol));\n }\n }\n else {\n // Special case for \"true\" and \"false\"\n // REVIEW: This may no longer be necessary?\n if (name == \"true\" || name == \"false\") {\n result.push(new ScopeEntry(name, \"bool\", this.compiler.typeChecker.booleanType.symbol));\n }\n }\n }\n\n return result;\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///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export enum Primitive {\n None = 0,\n Void = 1,\n Double = 2,\n String = 4,\n Boolean = 8,\n Any = 16,\n Null = 32,\n Undefined = 64,\n }\n\n export class MemberName {\n public prefix: string = \"\";\n public suffix: string = \"\";\n\n public isString() { return false; }\n public isArray() { return false; }\n\n public toString(): string {\n return MemberName.memberNameToString(this);\n }\n\n static memberNameToString(memberName: MemberName): string {\n var result = memberName.prefix;\n\n if (memberName.isString()) {\n result += (<MemberNameString>memberName).text;\n }\n else {\n var ar = <MemberNameArray>memberName;\n for (var index = 0; index < ar.entries.length; index++) {\n result += memberNameToString(ar.entries[index]);\n result += ar.delim;\n }\n }\n\n result += memberName.suffix;\n return result;\n }\n\n static create(text: string): MemberName;\n static create(entry: MemberName, prefix: string, suffix: string): MemberName;\n static create(arg1: any, arg2?: any, arg3?: any): MemberName {\n if (typeof arg1 == \"string\") {\n return new MemberNameString(arg1);\n }\n else {\n var result = new MemberNameArray();\n if (arg2)\n result.prefix = arg2;\n if (arg3)\n result.suffix = arg3;\n result.entries.push(arg1);\n return result;\n }\n }\n }\n\n export class MemberNameString extends MemberName {\n constructor (public text: string) {\n super()\n }\n\n public isString() { return true; }\n }\n\n export class MemberNameArray extends MemberName {\n public delim: string = \"\";\n public entries: MemberName[] = [];\n\n public isArray() { return true; }\n\n public add(entry: MemberName) {\n this.entries.push(entry);\n }\n\n public addAll(entries: MemberName[]) {\n for (var i = 0 ; i < entries.length; i++) {\n this.entries.push(entries[i]);\n }\n }\n }\n\n var currentTypeID = -1;\n\n export class Type {\n public typeID = currentTypeID++;\n\n public members: ScopedMembers;\n public ambientMembers: ScopedMembers;\n\n public construct: SignatureGroup = null;\n public call: SignatureGroup = null;\n public index: SignatureGroup = null;\n\n // REVIEW: for either of the below, why do we have lists of types and lists of type links?\n // interface can only extend\n public extendsList: Type[];\n public extendsTypeLinks: TypeLink[];\n\n // class can also implement\n public implementsList: Type[];\n public implementsTypeLinks: TypeLink[];\n\n public passTypeCreated: number = CompilerDiagnostics.analysisPass;\n\n public baseClass(): Type {\n if (this.extendsList && (this.extendsList.length > 0)) {\n return this.extendsList[0];\n }\n else {\n return null;\n }\n }\n\n public elementType: Type;\n\n public getArrayBase(arrInstType: Type, checker: TypeChecker): Type {\n return this.arrayCache.specialize(arrInstType, checker);\n }\n\n public primitiveTypeClass: number = Primitive.None;\n\n // REVIEW: Prune constructorScope\n public constructorScope: SymbolScope;\n public containedScope: SymbolScope;\n public memberScope: SymbolScope;\n\n public arrayCache: ArrayCache;\n\n public typeFlags = TypeFlags.None;\n\n public symbol: TypeSymbol;\n\n public enclosingType: Type;\n public instanceType: Type;\n\n // REVIEW: Prune\n public isClass() { return this.instanceType != null; }\n public isArray() { return this.elementType != null; }\n public isClassInstance() {\n return this.symbol && !this.elementType && (<TypeSymbol>this.symbol).type.isClass();\n }\n\n public getInstanceType() {\n if (this.isClass()) {\n return this.instanceType;\n }\n else {\n return this;\n }\n }\n\n public hasImplementation() { return hasFlag(this.typeFlags, TypeFlags.HasImplementation); }\n public setHasImplementation() { this.typeFlags |= TypeFlags.HasImplementation; }\n\n public isDouble() { return hasFlag(this.primitiveTypeClass, Primitive.Double); }\n public isString() { return hasFlag(this.primitiveTypeClass, Primitive.String); }\n public isBoolean() { return hasFlag(this.primitiveTypeClass, Primitive.Boolean); }\n public isNull() { return hasFlag(this.primitiveTypeClass, Primitive.Null); }\n\n // REVIEW: No need for this to be a method\n public getTypeName(): string {\n return this.getMemberTypeName(\"\", true, false, null);\n }\n\n public getScopedTypeName(scope: SymbolScope) {\n return this.getMemberTypeName(\"\", true, false, scope);\n }\n\n public getScopedTypeNameEx(scope: SymbolScope) {\n return this.getMemberTypeNameEx(\"\", true, false, scope);\n }\n\n // REVIEW: No need for this to be a method\n public callCount() {\n var total = 0;\n if (this.call) {\n total += this.call.signatures.length;\n }\n if (this.construct) {\n total += this.construct.signatures.length;\n }\n if (this.index) {\n total += this.index.signatures.length;\n }\n return total;\n }\n\n // REVIEW: No need for this to be a method\n public getMemberTypeName(prefix: string, topLevel: bool, isElementType: bool, scope: SymbolScope): string {\n var memberName = this.getMemberTypeNameEx(prefix, topLevel, isElementType, scope);\n return memberName.toString();\n }\n\n // REVIEW: No need for this to be a method\n public getMemberTypeNameEx(prefix: string, topLevel: bool, isElementType: bool, scope: SymbolScope): MemberName {\n if (this.elementType) {\n return MemberName.create(this.elementType.getMemberTypeNameEx(prefix, false, true, scope), \"\", \"[]\");\n }\n else if (this.symbol && this.symbol.name && this.symbol.name != \"_anonymous\" &&\n (((this.call == null) && (this.construct == null) && (this.index == null)) ||\n (hasFlag(this.typeFlags, TypeFlags.BuildingName)) ||\n (this.members && (!this.isClass())))) {\n var tn = this.symbol.scopeRelativeName(scope);\n return MemberName.create(tn == \"null\" ? \"any\" : tn); // REVIEW: GROSS!!!\n }\n else {\n if (this.members || this.call || this.construct) {\n if (hasFlag(this.typeFlags, TypeFlags.BuildingName)) {\n return MemberName.create(\"this\");\n }\n this.typeFlags |= TypeFlags.BuildingName;\n var builder = \"\";\n var allMemberNames = new MemberNameArray();\n var curlies = isElementType || this.index != null;\n var memCount = 0;\n var delim = \"; \";\n if (this.members) {\n this.members.allMembers.map((key, s, unused) => {\n var sym = <Symbol>s;\n if (!hasFlag(sym.flags, SymbolFlags.BuiltIn)) {\n // Remove the delimiter character from the generated type name, since\n // our \"allMemberNames\" array takes care of storing delimiters\n var typeNameMember = sym.getTypeNameEx(scope);\n if (typeNameMember.isArray() && (<MemberNameArray>typeNameMember).delim == delim) {\n allMemberNames.addAll((<MemberNameArray>typeNameMember).entries);\n } else {\n allMemberNames.add(typeNameMember);\n }\n memCount++;\n curlies = true;\n }\n }, null);\n }\n\n var signatureCount = this.callCount();\n var j: number;\n var len = 0;\n var shortform = !curlies && signatureCount == 1 && topLevel;\n if (this.call) {\n allMemberNames.addAll(this.call.toStrings(prefix, shortform, scope));\n }\n\n if (this.construct) {\n allMemberNames.addAll(this.construct.toStrings(\"new\", shortform, scope));\n }\n\n if (this.index) {\n allMemberNames.addAll(this.index.toStrings(\"\", shortform, scope));\n }\n\n if ((curlies) || ((signatureCount > 1) && topLevel)) {\n allMemberNames.prefix = \"{ \";\n allMemberNames.suffix = \"}\";\n allMemberNames.delim = delim;\n } else if (allMemberNames.entries.length > 1) {\n allMemberNames.delim = delim;\n }\n\n this.typeFlags &= (~TypeFlags.BuildingName);\n if ((signatureCount == 0) && (memCount == 0)) {\n return MemberName.create(\"{}\");\n }\n else {\n return allMemberNames;\n }\n }\n else {\n return MemberName.create(\"{}\");\n }\n }\n }\n\n public checkDecl(checker: TypeChecker) {\n if (this.isClassInstance() || this.isClass()) {\n if (this.symbol.declAST) {\n checker.typeFlow.inScopeTypeCheckDecl(this.symbol.declAST);\n }\n }\n }\n\n public getMemberScope(flow: TypeFlow) {\n if (this == flow.anyType) {\n return null;\n }\n else if (this.isDouble()) {\n if (flow.numberInterfaceType) {\n return flow.numberInterfaceType.memberScope;\n }\n else {\n return null;\n }\n }\n else if (this.isBoolean()) {\n if (flow.booleanInterfaceType) {\n return flow.booleanInterfaceType.memberScope;\n }\n else {\n return null;\n }\n }\n else if (this == flow.stringType) {\n if (flow.stringInterfaceType) {\n return flow.stringInterfaceType.memberScope;\n }\n else {\n return null;\n }\n }\n else if (this.elementType) {\n if (flow.arrayInterfaceType) {\n var arrInstType = this.elementType.getArrayBase(flow.arrayInterfaceType, flow.checker);\n return arrInstType.memberScope;\n }\n else {\n return null;\n }\n }\n else {\n return this.memberScope;\n }\n }\n\n public isReferenceType() {\n return this.members || this.extendsList ||\n this.construct || this.call || this.index ||\n this.elementType;\n }\n\n public specializeType(pattern: Type, replacement: Type, checker: TypeChecker, membersOnly: bool): Type {\n if (pattern == this) {\n return replacement;\n }\n var result = this;\n if (membersOnly) {\n // assume interface type without bases\n if (this.isReferenceType()) {\n result = new Type();\n if (this.members) {\n result.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n this.members.publicMembers.map((key, s, unused) => {\n var sym = <Symbol>s;\n var bSym = sym.specializeType(pattern, replacement, checker);\n result.members.addPublicMember(bSym.name, bSym);\n }, null);\n\n this.members.privateMembers.map((key, s, unused) => {\n var sym = <Symbol>s;\n var bSym = sym.specializeType(pattern, replacement, checker);\n result.members.addPrivateMember(bSym.name, bSym);\n }, null);\n }\n if (this.ambientMembers) {\n result.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n this.ambientMembers.publicMembers.map((key, s, unused) => {\n var sym = <Symbol>s;\n var bSym = sym.specializeType(pattern, replacement, checker);\n result.ambientMembers.addPublicMember(bSym.name, bSym);\n }, null);\n\n this.ambientMembers.privateMembers.map((key, s, unused) => {\n var sym = <Symbol>s;\n var bSym = sym.specializeType(pattern, replacement, checker);\n result.ambientMembers.addPrivateMember(bSym.name, bSym);\n }, null);\n }\n result.containedScope = checker.scopeOf(result);\n result.memberScope = result.containedScope;\n }\n }\n else {\n if (this.elementType) {\n if (this.elementType == pattern) {\n result = checker.makeArrayType(replacement);\n }\n else {\n if (this.elementType.elementType == pattern) {\n result = checker.makeArrayType(checker.makeArrayType(replacement));\n }\n }\n }\n else if (this.call) {\n result = new Type();\n result.call = this.call.specializeType(pattern, replacement, checker);\n }\n }\n return result;\n }\n\n public hasBase(baseType: Type): bool {\n if (baseType == this) {\n return true;\n }\n else {\n if (this.extendsList) {\n for (var i = 0, len = this.extendsList.length; i < len; i++) {\n if (this.extendsList[i].hasBase(baseType)) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n public mergeOrdered(b: Type, checker: TypeChecker, acceptVoid: bool, comparisonInfo?: TypeComparisonInfo): Type {\n if ((this == checker.anyType) || (b == checker.anyType)) {\n return checker.anyType;\n }\n else if (this == b) {\n return this;\n }\n else if ((b == checker.nullType) && this != checker.nullType) {\n return this;\n }\n else if ((this == checker.nullType) && (b != checker.nullType)) {\n return b;\n }\n else if (acceptVoid && (b == checker.voidType) && this != checker.voidType) {\n return this;\n }\n else if (acceptVoid && (this == checker.voidType) && (b != checker.voidType)) {\n return b;\n }\n else if ((b == checker.undefinedType) && this != checker.undefinedType) {\n return this;\n }\n else if ((this == checker.undefinedType) && (b != checker.undefinedType)) {\n return b;\n }\n else if (this.elementType && b.elementType) {\n if (this.elementType == b.elementType) {\n return this;\n }\n else {\n var mergedET = this.elementType.mergeOrdered(b.elementType, checker, acceptVoid, comparisonInfo);\n if (mergedET == null) {\n return checker.makeArrayType(checker.anyType);\n }\n else {\n return checker.makeArrayType(mergedET);\n }\n }\n }\n else if (checker.sourceIsSubtypeOfTarget(this, b, comparisonInfo)) {\n return b;\n }\n else if (checker.sourceIsSubtypeOfTarget(b, this, comparisonInfo)) {\n return this;\n }\n else {\n return null;\n }\n }\n\n public isModuleType() { return false; }\n public hasMembers() { return this.members != null; }\n public getAllEnclosedTypes(): ScopedMembers { return null; }\n public getAllAmbientEnclosedTypes(): ScopedMembers { return null; }\n public getPublicEnclosedTypes(): ScopedMembers { return null; }\n public getpublicAmbientEnclosedTypes(): ScopedMembers { return null; }\n\n public getDocComments(): Comment[]{\n if (this.elementType || !this.symbol) {\n return [];\n }\n\n if (this.isClassInstance() || this.isClass()) {\n if (this.symbol.declAST.nodeType == NodeType.FuncDecl) {\n // Its a constructor - use the class declaration instead\n return (<FuncDecl>this.symbol.declAST).classDecl.getDocComments();\n } else {\n // Its a class without constructor\n return this.symbol.getDocComments();\n }\n }\n\n if (this.symbol.name && this.symbol.name != \"_anonymous\" &&\n (((this.call == null) && (this.construct == null) && (this.index == null))\n || this.members)) {\n return this.symbol.getDocComments();\n }\n\n return [];\n }\n }\n\n export interface ITypeCollection {\n // returns null when types are exhausted\n getLength(): number;\n setTypeAtIndex(index: number, type: Type): void;\n getTypeAtIndex(index: number): Type;\n }\n\n export class ModuleType extends Type {\n\n constructor (public enclosedTypes: ScopedMembers, public ambientEnclosedTypes: ScopedMembers) {\n super();\n }\n\n public isModuleType() { return true; }\n public hasMembers() { return this.members != null || this.enclosedTypes != null; }\n public getAllEnclosedTypes() { return this.enclosedTypes; }\n public getAllAmbientEnclosedTypes() { return this.ambientEnclosedTypes; }\n public getPublicEnclosedTypes(): ScopedMembers { return null; }\n public getpublicAmbientEnclosedTypes(): ScopedMembers { return null; }\n public importedModules: ImportDeclaration[] = [];\n\n // Finds the dynamic module name of moduleType in the members\n // ignoreSymbols define list of symbols already visited - to avoid recursion\n static findDynamicModuleNameInHashTable(moduleType: Type, members: IHashTable) {\n var moduleName: { name: string; symbol: Symbol; } = null;\n members.map((key, s, c) => {\n if (moduleName == null && !isQuoted(key)) {\n var symbol = <Symbol>s;\n var type = symbol.getType();\n if (type == moduleType) {\n // If this is the module type we were looking for\n moduleName = { name: key, symbol: symbol };\n }\n }\n }, null);\n\n return moduleName;\n }\n\n // Finds the Dynamic module name of the moduleType in this moduleType\n // onlyPublic tells if we are looking for module name in public members only\n public findDynamicModuleName(moduleType: Type): { name: string; symbol: Symbol; } {\n var moduleName: { name: string; symbol: Symbol; } = null;\n // Not cached, so seach and add to the cache\n moduleName = ModuleType.findDynamicModuleNameInHashTable(moduleType, this.members.allMembers);\n if (moduleName == null) {\n moduleName = ModuleType.findDynamicModuleNameInHashTable(moduleType, this.ambientMembers.allMembers);\n }\n return moduleName;\n }\n }\n\n export class TypeLink {\n public type: Type = null;\n public ast: AST = null;\n }\n\n export function getTypeLink(ast: AST, checker: TypeChecker, autoVar: bool): TypeLink {\n var result = new TypeLink();\n\n result.ast = ast;\n\n if ((ast == null) && (autoVar)) {\n result.type = checker.anyType;\n }\n else {\n result.type = null;\n }\n\n return result;\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///<reference path='typescript.ts' />\n\nmodule Tools {\n export interface IWalkContext {\n goChildren: bool;\n goNextSibling: bool;\n // visit siblings in reverse execution order\n reverseSiblings: bool;\n }\n\n export class BaseWalkContext implements IWalkContext {\n public goChildren = true;\n public goNextSibling = true;\n public reverseSiblings = false;\n }\n}"