• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//// [parserRealSource11.ts]
2// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
3// See LICENSE.txt in the project root for complete license information.
4
5///<reference path='typescript.ts' />
6
7module TypeScript {
8    export class ASTSpan {
9        public minChar: number = -1;  // -1 = "undefined" or "compiler generated"
10        public limChar: number = -1;  // -1 = "undefined" or "compiler generated"
11    }
12
13    export class AST extends ASTSpan {
14        public type: Type = null;
15        public flags = ASTFlags.Writeable;
16
17        // REVIEW: for diagnostic purposes
18        public passCreated: number = CompilerDiagnostics.analysisPass;
19
20        public preComments: Comment[] = null;
21        public postComments: Comment[] = null;
22
23        public isParenthesized = false;
24
25        constructor (public nodeType: NodeType) {
26            super();
27        }
28
29        public isExpression() { return false; }
30
31        public isStatementOrExpression() { return false; }
32
33        public isCompoundStatement() { return false; }
34
35        public isLeaf() { return this.isStatementOrExpression() && (!this.isCompoundStatement()); }
36
37        public typeCheck(typeFlow: TypeFlow) {
38            switch (this.nodeType) {
39                case NodeType.Error:
40                case NodeType.EmptyExpr:
41                    this.type = typeFlow.anyType;
42                    break;
43                case NodeType.This:
44                    return typeFlow.typeCheckThis(this);
45                case NodeType.Null:
46                    this.type = typeFlow.nullType;
47                    break;
48                case NodeType.False:
49                case NodeType.True:
50                    this.type = typeFlow.booleanType;
51                    break;
52                case NodeType.Super:
53                    return typeFlow.typeCheckSuper(this);
54                case NodeType.EndCode:
55                case NodeType.Empty:
56                case NodeType.Void:
57                    this.type = typeFlow.voidType;
58                    break;
59                default:
60                    throw new Error("please implement in derived class");
61            }
62            return this;
63        }
64
65        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
66            emitter.emitParensAndCommentsInPlace(this, true);
67            switch (this.nodeType) {
68                case NodeType.This:
69                    emitter.recordSourceMappingStart(this);
70                    if (emitter.thisFnc && (hasFlag(emitter.thisFnc.fncFlags, FncFlags.IsFatArrowFunction))) {
71                        emitter.writeToOutput("_this");
72                    }
73                    else {
74                        emitter.writeToOutput("this");
75                    }
76                    emitter.recordSourceMappingEnd(this);
77                    break;
78                case NodeType.Null:
79                    emitter.recordSourceMappingStart(this);
80                    emitter.writeToOutput("null");
81                    emitter.recordSourceMappingEnd(this);
82                    break;
83                case NodeType.False:
84                    emitter.recordSourceMappingStart(this);
85                    emitter.writeToOutput("false");
86                    emitter.recordSourceMappingEnd(this);
87                    break;
88                case NodeType.True:
89                    emitter.recordSourceMappingStart(this);
90                    emitter.writeToOutput("true");
91                    emitter.recordSourceMappingEnd(this);
92                    break;
93                case NodeType.Super:
94                    emitter.recordSourceMappingStart(this);
95                    emitter.emitSuperReference();
96                    emitter.recordSourceMappingEnd(this);
97                    break;
98                case NodeType.EndCode:
99                    break;
100                case NodeType.Error:
101                case NodeType.EmptyExpr:
102                    break;
103
104                case NodeType.Empty:
105                    emitter.recordSourceMappingStart(this);
106                    emitter.writeToOutput("; ");
107                    emitter.recordSourceMappingEnd(this);
108                    break;
109                case NodeType.Void:
110                    emitter.recordSourceMappingStart(this);
111                    emitter.writeToOutput("void ");
112                    emitter.recordSourceMappingEnd(this);
113                    break;
114                default:
115                    throw new Error("please implement in derived class");
116            }
117            emitter.emitParensAndCommentsInPlace(this, false);
118        }
119
120        public print(context: PrintContext) {
121            context.startLine();
122            var lineCol = { line: -1, col: -1 };
123            var limLineCol = { line: -1, col: -1 };
124            if (context.parser !== null) {
125                context.parser.getSourceLineCol(lineCol, this.minChar);
126                context.parser.getSourceLineCol(limLineCol, this.limChar);
127                context.write("(" + lineCol.line + "," + lineCol.col + ")--" +
128                              "(" + limLineCol.line + "," + limLineCol.col + "): ");
129            }
130            var lab = this.printLabel();
131            if (hasFlag(this.flags, ASTFlags.Error)) {
132                lab += " (Error)";
133            }
134            context.writeLine(lab);
135        }
136
137        public printLabel() {
138            if (nodeTypeTable[this.nodeType] !== undefined) {
139                return nodeTypeTable[this.nodeType];
140            }
141            else {
142                return (<any>NodeType)._map[this.nodeType];
143            }
144        }
145
146        public addToControlFlow(context: ControlFlowContext): void {
147            // by default, AST adds itself to current basic block and does not check its children
148            context.walker.options.goChildren = false;
149            context.addContent(this);
150        }
151
152        public netFreeUses(container: Symbol, freeUses: StringHashTable) {
153        }
154
155        public treeViewLabel() {
156            return (<any>NodeType)._map[this.nodeType];
157        }
158
159        public static getResolvedIdentifierName(name: string): string {
160            if (!name) return "";
161
162            var resolved = "";
163            var start = 0;
164            var i = 0;
165            while(i <= name.length - 6) {
166                // Look for escape sequence \uxxxx
167                if (name.charAt(i) == '\\' && name.charAt(i+1) == 'u') {
168                    var charCode = parseInt(name.substr(i + 2, 4), 16);
169                    resolved += name.substr(start, i - start);
170                    resolved += String.fromCharCode(charCode);
171                    i += 6;
172                    start = i;
173                    continue;
174                }
175                i++;
176            }
177            // Append remaining string
178            resolved += name.substring(start);
179            return resolved;
180        }
181    }
182
183    export class IncompleteAST extends AST {
184        constructor (min: number, lim: number) {
185            super(NodeType.Error);
186
187            this.minChar = min;
188            this.limChar = lim;
189        }
190    }
191
192    export class ASTList extends AST {
193        public enclosingScope: SymbolScope = null;
194        public members: AST[] = new AST[];
195
196        constructor () {
197            super(NodeType.List);
198        }
199
200        public addToControlFlow(context: ControlFlowContext) {
201            var len = this.members.length;
202            for (var i = 0; i < len; i++) {
203                if (context.noContinuation) {
204                    context.addUnreachable(this.members[i]);
205                    break;
206                }
207                else {
208                    this.members[i] = context.walk(this.members[i], this);
209                }
210            }
211            context.walker.options.goChildren = false;
212        }
213
214        public append(ast: AST) {
215            this.members[this.members.length] = ast;
216            return this;
217        }
218
219        public appendAll(ast: AST) {
220            if (ast.nodeType == NodeType.List) {
221                var list = <ASTList>ast;
222                for (var i = 0, len = list.members.length; i < len; i++) {
223                    this.append(list.members[i]);
224                }
225            }
226            else {
227                this.append(ast);
228            }
229            return this;
230        }
231
232        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
233            emitter.recordSourceMappingStart(this);
234            emitter.emitJavascriptList(this, null, TokenID.Semicolon, startLine, false, false);
235            emitter.recordSourceMappingEnd(this);
236        }
237
238        public typeCheck(typeFlow: TypeFlow) {
239            var len = this.members.length;
240            typeFlow.nestingLevel++;
241            for (var i = 0; i < len; i++) {
242                if (this.members[i]) {
243                    this.members[i] = this.members[i].typeCheck(typeFlow);
244                }
245            }
246            typeFlow.nestingLevel--;
247            return this;
248        }
249    }
250
251    export class Identifier extends AST {
252        public sym: Symbol = null;
253        public cloId = -1;
254        public text: string;
255
256        // 'actualText' is the text that the user has entered for the identifier. the text might
257        // include any Unicode escape sequences (e.g.: \u0041 for 'A'). 'text', however, contains
258        // the resolved value of any escape sequences in the actual text; so in the previous
259        // example, actualText = '\u0041', text = 'A'.
260        //
261        // For purposes of finding a symbol, use text, as this will allow you to match all
262        // variations of the variable text. For full-fidelity translation of the user input, such
263        // as emitting, use the actualText field.
264        //
265        // Note:
266        //    To change text, and to avoid running into a situation where 'actualText' does not
267        //    match 'text', always use setText.
268        constructor (public actualText: string, public hasEscapeSequence?: boolean) {
269            super(NodeType.Name);
270            this.setText(actualText, hasEscapeSequence);
271        }
272
273        public setText(actualText: string, hasEscapeSequence?: boolean) {
274            this.actualText = actualText;
275            if (hasEscapeSequence) {
276                this.text = AST.getResolvedIdentifierName(actualText);
277            }
278            else {
279                this.text = actualText;
280            }
281        }
282
283        public isMissing() { return false; }
284        public isLeaf() { return true; }
285
286        public treeViewLabel() {
287            return "id: " + this.actualText;
288        }
289
290        public printLabel() {
291            if (this.actualText) {
292                return "id: " + this.actualText;
293            }
294            else {
295                return "name node";
296            }
297        }
298
299        public typeCheck(typeFlow: TypeFlow) {
300            return typeFlow.typeCheckName(this);
301        }
302
303        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
304            emitter.emitJavascriptName(this, true);
305        }
306
307        public static fromToken(token: Token): Identifier {
308            return new Identifier(token.getText(), (<IdentifierToken>token).hasEscapeSequence);
309        }
310    }
311
312    export class MissingIdentifier extends Identifier {
313        constructor () {
314            super("__missing");
315        }
316
317        public isMissing() {
318            return true;
319        }
320
321        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
322            // Emit nothing for a missing ID
323        }
324    }
325
326    export class Label extends AST {
327        constructor (public id: Identifier) {
328            super(NodeType.Label);
329        }
330
331        public printLabel() { return this.id.actualText + ":"; }
332
333        public typeCheck(typeFlow: TypeFlow) {
334            this.type = typeFlow.voidType;
335            return this;
336        }
337
338        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
339            emitter.emitParensAndCommentsInPlace(this, true);
340            emitter.recordSourceMappingStart(this);
341            emitter.recordSourceMappingStart(this.id);
342            emitter.writeToOutput(this.id.actualText);
343            emitter.recordSourceMappingEnd(this.id);
344            emitter.writeLineToOutput(":");
345            emitter.recordSourceMappingEnd(this);
346            emitter.emitParensAndCommentsInPlace(this, false);
347        }
348    }
349
350    export class Expression extends AST {
351        constructor (nodeType: NodeType) {
352            super(nodeType);
353        }
354
355        public isExpression() { return true; }
356
357        public isStatementOrExpression() { return true; }
358    }
359
360    export class UnaryExpression extends Expression {
361        public targetType: Type = null; // Target type for an object literal (null if no target type)
362        public castTerm: AST = null;
363
364        constructor (nodeType: NodeType, public operand: AST) {
365            super(nodeType);
366        }
367
368        public addToControlFlow(context: ControlFlowContext): void {
369            super.addToControlFlow(context);
370            // TODO: add successor as catch block/finally block if present
371            if (this.nodeType == NodeType.Throw) {
372                context.returnStmt();
373            }
374        }
375
376        public typeCheck(typeFlow: TypeFlow) {
377            switch (this.nodeType) {
378                case NodeType.Not:
379                    return typeFlow.typeCheckBitNot(this);
380
381                case NodeType.LogNot:
382                    return typeFlow.typeCheckLogNot(this);
383
384                case NodeType.Pos:
385                case NodeType.Neg:
386                    return typeFlow.typeCheckUnaryNumberOperator(this);
387
388                case NodeType.IncPost:
389                case NodeType.IncPre:
390                case NodeType.DecPost:
391                case NodeType.DecPre:
392                    return typeFlow.typeCheckIncOrDec(this);
393
394                case NodeType.ArrayLit:
395                    typeFlow.typeCheckArrayLit(this);
396                    return this;
397
398                case NodeType.ObjectLit:
399                    typeFlow.typeCheckObjectLit(this);
400                    return this;
401
402                case NodeType.Throw:
403                    this.operand = typeFlow.typeCheck(this.operand);
404                    this.type = typeFlow.voidType;
405                    return this;
406
407                case NodeType.Typeof:
408                    this.operand = typeFlow.typeCheck(this.operand);
409                    this.type = typeFlow.stringType;
410                    return this;
411
412                case NodeType.Delete:
413                    this.operand = typeFlow.typeCheck(this.operand);
414                    this.type = typeFlow.booleanType;
415                    break;
416
417                case NodeType.TypeAssertion:
418                    this.castTerm = typeFlow.typeCheck(this.castTerm);
419                    var applyTargetType = !this.operand.isParenthesized;
420
421                    var targetType = applyTargetType ? this.castTerm.type : null;
422
423                    typeFlow.checker.typeCheckWithContextualType(targetType, typeFlow.checker.inProvisionalTypecheckMode(), true, this.operand);
424                    typeFlow.castWithCoercion(this.operand, this.castTerm.type, false, true);
425                    this.type = this.castTerm.type;
426                    return this;
427
428                case NodeType.Void:
429                    // REVIEW - Although this is good to do for completeness's sake,
430                    // this shouldn't be strictly necessary from the void operator's
431                    // point of view
432                    this.operand = typeFlow.typeCheck(this.operand);
433                    this.type = typeFlow.checker.undefinedType;
434                    break;
435
436                default:
437                    throw new Error("please implement in derived class");
438            }
439            return this;
440        }
441
442        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
443            emitter.emitParensAndCommentsInPlace(this, true);
444            emitter.recordSourceMappingStart(this);
445            switch (this.nodeType) {
446                case NodeType.IncPost:
447                    emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);
448                    emitter.writeToOutput("++");
449                    break;
450                case NodeType.LogNot:
451                    emitter.writeToOutput("!");
452                    emitter.emitJavascript(this.operand, TokenID.Exclamation, false);
453                    break;
454                case NodeType.DecPost:
455                    emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);
456                    emitter.writeToOutput("--");
457                    break;
458                case NodeType.ObjectLit:
459                    emitter.emitObjectLiteral(<ASTList>this.operand);
460                    break;
461                case NodeType.ArrayLit:
462                    emitter.emitArrayLiteral(<ASTList>this.operand);
463                    break;
464                case NodeType.Not:
465                    emitter.writeToOutput("~");
466                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
467                    break;
468                case NodeType.Neg:
469                    emitter.writeToOutput("-");
470                    if (this.operand.nodeType == NodeType.Neg) {
471                        this.operand.isParenthesized = true;
472                    }
473                    emitter.emitJavascript(this.operand, TokenID.Minus, false);
474                    break;
475                case NodeType.Pos:
476                    emitter.writeToOutput("+");
477                    if (this.operand.nodeType == NodeType.Pos) {
478                        this.operand.isParenthesized = true;
479                    }
480                    emitter.emitJavascript(this.operand, TokenID.Plus, false);
481                    break;
482                case NodeType.IncPre:
483                    emitter.writeToOutput("++");
484                    emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);
485                    break;
486                case NodeType.DecPre:
487                    emitter.writeToOutput("--");
488                    emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);
489                    break;
490                case NodeType.Throw:
491                    emitter.writeToOutput("throw ");
492                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
493                    emitter.writeToOutput(";");
494                    break;
495                case NodeType.Typeof:
496                    emitter.writeToOutput("typeof ");
497                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
498                    break;
499                case NodeType.Delete:
500                    emitter.writeToOutput("delete ");
501                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
502                    break;
503                case NodeType.Void:
504                    emitter.writeToOutput("void ");
505                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
506                    break;
507                case NodeType.TypeAssertion:
508                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
509                    break;
510                default:
511                    throw new Error("please implement in derived class");
512            }
513            emitter.recordSourceMappingEnd(this);
514            emitter.emitParensAndCommentsInPlace(this, false);
515        }
516    }
517
518    export class CallExpression extends Expression {
519        constructor (nodeType: NodeType,
520                     public target: AST,
521                     public arguments: ASTList) {
522            super(nodeType);
523            this.minChar = this.target.minChar;
524        }
525
526        public signature: Signature = null;
527
528        public typeCheck(typeFlow: TypeFlow) {
529            if (this.nodeType == NodeType.New) {
530                return typeFlow.typeCheckNew(this);
531            }
532            else {
533                return typeFlow.typeCheckCall(this);
534            }
535        }
536
537        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
538            emitter.emitParensAndCommentsInPlace(this, true);
539            emitter.recordSourceMappingStart(this);
540
541            if (this.nodeType == NodeType.New) {
542                emitter.emitNew(this.target, this.arguments);
543            }
544            else {
545                emitter.emitCall(this, this.target, this.arguments);
546            }
547
548            emitter.recordSourceMappingEnd(this);
549            emitter.emitParensAndCommentsInPlace(this, false);
550        }
551    }
552
553    export class BinaryExpression extends Expression {
554        constructor (nodeType: NodeType, public operand1: AST, public operand2: AST) {
555            super(nodeType);
556        }
557
558        public typeCheck(typeFlow: TypeFlow) {
559            switch (this.nodeType) {
560                case NodeType.Dot:
561                    return typeFlow.typeCheckDotOperator(this);
562                case NodeType.Asg:
563                    return typeFlow.typeCheckAsgOperator(this);
564                case NodeType.Add:
565                case NodeType.Sub:
566                case NodeType.Mul:
567                case NodeType.Div:
568                case NodeType.Mod:
569                case NodeType.Or:
570                case NodeType.And:
571                    return typeFlow.typeCheckArithmeticOperator(this, false);
572                case NodeType.Xor:
573                    return typeFlow.typeCheckBitwiseOperator(this, false);
574                case NodeType.Ne:
575                case NodeType.Eq:
576                    var text: string;
577                    if (typeFlow.checker.styleSettings.eqeqeq) {
578                        text = nodeTypeTable[this.nodeType];
579                        typeFlow.checker.errorReporter.styleError(this, "use of " + text);
580                    }
581                    else if (typeFlow.checker.styleSettings.eqnull) {
582                        text = nodeTypeTable[this.nodeType];
583                        if ((this.operand2 !== null) && (this.operand2.nodeType == NodeType.Null)) {
584                            typeFlow.checker.errorReporter.styleError(this, "use of " + text + " to compare with null");
585                        }
586                    }
587                case NodeType.Eqv:
588                case NodeType.NEqv:
589                case NodeType.Lt:
590                case NodeType.Le:
591                case NodeType.Ge:
592                case NodeType.Gt:
593                    return typeFlow.typeCheckBooleanOperator(this);
594                case NodeType.Index:
595                    return typeFlow.typeCheckIndex(this);
596                case NodeType.Member:
597                    this.type = typeFlow.voidType;
598                    return this;
599                case NodeType.LogOr:
600                    return typeFlow.typeCheckLogOr(this);
601                case NodeType.LogAnd:
602                    return typeFlow.typeCheckLogAnd(this);
603                case NodeType.AsgAdd:
604                case NodeType.AsgSub:
605                case NodeType.AsgMul:
606                case NodeType.AsgDiv:
607                case NodeType.AsgMod:
608                case NodeType.AsgOr:
609                case NodeType.AsgAnd:
610                    return typeFlow.typeCheckArithmeticOperator(this, true);
611                case NodeType.AsgXor:
612                    return typeFlow.typeCheckBitwiseOperator(this, true);
613                case NodeType.Lsh:
614                case NodeType.Rsh:
615                case NodeType.Rs2:
616                    return typeFlow.typeCheckShift(this, false);
617                case NodeType.AsgLsh:
618                case NodeType.AsgRsh:
619                case NodeType.AsgRs2:
620                    return typeFlow.typeCheckShift(this, true);
621                case NodeType.Comma:
622                    return typeFlow.typeCheckCommaOperator(this);
623                case NodeType.InstOf:
624                    return typeFlow.typeCheckInstOf(this);
625                case NodeType.In:
626                    return typeFlow.typeCheckInOperator(this);
627                case NodeType.From:
628                    typeFlow.checker.errorReporter.simpleError(this, "Illegal use of 'from' keyword in binary expression");
629                    break;
630                default:
631                    throw new Error("please implement in derived class");
632            }
633            return this;
634        }
635
636        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
637            var binTokenId = nodeTypeToTokTable[this.nodeType];
638
639            emitter.emitParensAndCommentsInPlace(this, true);
640            emitter.recordSourceMappingStart(this);
641            if (binTokenId != undefined) {
642
643                emitter.emitJavascript(this.operand1, binTokenId, false);
644
645                if (tokenTable[binTokenId].text == "instanceof") {
646                    emitter.writeToOutput(" instanceof ");
647                }
648                else if (tokenTable[binTokenId].text == "in") {
649                    emitter.writeToOutput(" in ");
650                }
651                else {
652                    emitter.writeToOutputTrimmable(" " + tokenTable[binTokenId].text + " ");
653                }
654
655                emitter.emitJavascript(this.operand2, binTokenId, false);
656            }
657            else {
658                switch (this.nodeType) {
659                    case NodeType.Dot:
660                        if (!emitter.tryEmitConstant(this)) {
661                            emitter.emitJavascript(this.operand1, TokenID.Dot, false);
662                            emitter.writeToOutput(".");
663                            emitter.emitJavascriptName(<Identifier>this.operand2, false);
664                        }
665                        break;
666                    case NodeType.Index:
667                        emitter.emitIndex(this.operand1, this.operand2);
668                        break;
669
670                    case NodeType.Member:
671                        if (this.operand2.nodeType == NodeType.FuncDecl && (<FuncDecl>this.operand2).isAccessor()) {
672                            var funcDecl = <FuncDecl>this.operand2;
673                            if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {
674                                emitter.writeToOutput("get ");
675                            }
676                            else {
677                                emitter.writeToOutput("set ");
678                            }
679                            emitter.emitJavascript(this.operand1, TokenID.Colon, false);
680                        }
681                        else {
682                            emitter.emitJavascript(this.operand1, TokenID.Colon, false);
683                            emitter.writeToOutputTrimmable(": ");
684                        }
685                        emitter.emitJavascript(this.operand2, TokenID.Comma, false);
686                        break;
687                    case NodeType.Comma:
688                        emitter.emitJavascript(this.operand1, TokenID.Comma, false);
689                        if (emitter.emitState.inObjectLiteral) {
690                            emitter.writeLineToOutput(", ");
691                        }
692                        else {
693                            emitter.writeToOutput(",");
694                        }
695                        emitter.emitJavascript(this.operand2, TokenID.Comma, false);
696                        break;
697                    case NodeType.Is:
698                        throw new Error("should be de-sugared during type check");
699                    default:
700                        throw new Error("please implement in derived class");
701                }
702            }
703            emitter.recordSourceMappingEnd(this);
704            emitter.emitParensAndCommentsInPlace(this, false);
705        }
706    }
707
708    export class ConditionalExpression extends Expression {
709        constructor (public operand1: AST,
710                     public operand2: AST,
711                     public operand3: AST) {
712            super(NodeType.ConditionalExpression);
713        }
714
715        public typeCheck(typeFlow: TypeFlow) {
716            return typeFlow.typeCheckQMark(this);
717        }
718
719        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
720            emitter.emitParensAndCommentsInPlace(this, true);
721            emitter.recordSourceMappingStart(this);
722            emitter.emitJavascript(this.operand1, TokenID.Question, false);
723            emitter.writeToOutput(" ? ");
724            emitter.emitJavascript(this.operand2, TokenID.Question, false);
725            emitter.writeToOutput(" : ");
726            emitter.emitJavascript(this.operand3, TokenID.Question, false);
727            emitter.recordSourceMappingEnd(this);
728            emitter.emitParensAndCommentsInPlace(this, false);
729        }
730    }
731
732    export class NumberLiteral extends Expression {
733        constructor (public value: number, public hasEmptyFraction?: boolean) {
734            super(NodeType.NumberLit);
735        }
736
737        public isNegativeZero = false;
738
739        public typeCheck(typeFlow: TypeFlow) {
740            this.type = typeFlow.doubleType;
741            return this;
742        }
743
744        public treeViewLabel() {
745            return "num: " + this.printLabel();
746        }
747
748        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
749            emitter.emitParensAndCommentsInPlace(this, true);
750            emitter.recordSourceMappingStart(this);
751            if (this.isNegativeZero) {
752                emitter.writeToOutput("-");
753            }
754
755            emitter.writeToOutput(this.value.toString());
756
757            if (this.hasEmptyFraction)
758                emitter.writeToOutput(".0");
759
760            emitter.recordSourceMappingEnd(this);
761            emitter.emitParensAndCommentsInPlace(this, false);
762        }
763
764        public printLabel() {
765            if (Math.floor(this.value) != this.value) {
766                return this.value.toFixed(2).toString();
767            }
768            else if (this.hasEmptyFraction) {
769                return this.value.toString() + ".0";
770            }
771            else {
772                return this.value.toString();
773            }
774        }
775    }
776
777    export class RegexLiteral extends Expression {
778        constructor (public regex) {
779            super(NodeType.Regex);
780        }
781
782        public typeCheck(typeFlow: TypeFlow) {
783            this.type = typeFlow.regexType;
784            return this;
785        }
786
787        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
788            emitter.emitParensAndCommentsInPlace(this, true);
789            emitter.recordSourceMappingStart(this);
790            emitter.writeToOutput(this.regex.toString());
791            emitter.recordSourceMappingEnd(this);
792            emitter.emitParensAndCommentsInPlace(this, false);
793        }
794    }
795
796    export class StringLiteral extends Expression {
797        constructor (public text: string) {
798            super(NodeType.QString);
799        }
800
801        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
802            emitter.emitParensAndCommentsInPlace(this, true);
803            emitter.recordSourceMappingStart(this);
804            emitter.emitStringLiteral(this.text);
805            emitter.recordSourceMappingEnd(this);
806            emitter.emitParensAndCommentsInPlace(this, false);
807        }
808
809        public typeCheck(typeFlow: TypeFlow) {
810            this.type = typeFlow.stringType;
811            return this;
812        }
813
814        public treeViewLabel() {
815            return "st: " + this.text;
816        }
817
818        public printLabel() {
819            return this.text;
820        }
821    }
822
823    export class ModuleElement extends AST {
824        constructor (nodeType: NodeType) {
825            super(nodeType);
826        }
827    }
828
829    export class ImportDeclaration extends ModuleElement {
830        public isStatementOrExpression() { return true; }
831        public varFlags = VarFlags.None;
832        public isDynamicImport = false;
833
834        constructor (public id: Identifier, public alias: AST) {
835            super(NodeType.ImportDeclaration);
836        }
837
838        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
839            var mod = <ModuleType>this.alias.type;
840            // REVIEW: Only modules may be aliased for now, though there's no real
841            // restriction on what the type symbol may be
842            if (!this.isDynamicImport || (this.id.sym && !(<TypeSymbol>this.id.sym).onlyReferencedAsTypeRef)) {
843                var prevModAliasId = emitter.modAliasId;
844                var prevFirstModAlias = emitter.firstModAlias;
845
846                emitter.recordSourceMappingStart(this);
847                emitter.emitParensAndCommentsInPlace(this, true);
848                emitter.writeToOutput("var " + this.id.actualText + " = ");
849                emitter.modAliasId = this.id.actualText;
850                emitter.firstModAlias = this.firstAliasedModToString();
851                emitter.emitJavascript(this.alias, TokenID.Tilde, false);
852                // the dynamic import case will insert the semi-colon automatically
853                if (!this.isDynamicImport) {
854                    emitter.writeToOutput(";");
855                }
856                emitter.emitParensAndCommentsInPlace(this, false);
857                emitter.recordSourceMappingEnd(this);
858
859                emitter.modAliasId = prevModAliasId;
860                emitter.firstModAlias = prevFirstModAlias;
861            }
862        }
863
864        public typeCheck(typeFlow: TypeFlow) {
865            return typeFlow.typeCheckImportDecl(this);
866        }
867
868        public getAliasName(aliasAST?: AST = this.alias) : string {
869            if (aliasAST.nodeType == NodeType.Name) {
870                return (<Identifier>aliasAST).actualText;
871            } else {
872                var dotExpr = <BinaryExpression>aliasAST;
873                return this.getAliasName(dotExpr.operand1) + "." + this.getAliasName(dotExpr.operand2);
874            }
875        }
876
877        public firstAliasedModToString() {
878            if (this.alias.nodeType == NodeType.Name) {
879                return (<Identifier>this.alias).actualText;
880            }
881            else {
882                var dotExpr = <BinaryExpression>this.alias;
883                var firstMod = <Identifier>dotExpr.operand1;
884                return firstMod.actualText;
885            }
886        }
887    }
888
889    export class BoundDecl extends AST {
890        public init: AST = null;
891        public typeExpr: AST = null;
892        public varFlags = VarFlags.None;
893        public sym: Symbol = null;
894
895        constructor (public id: Identifier, nodeType: NodeType, public nestingLevel: number) {
896            super(nodeType);
897        }
898
899        public isStatementOrExpression() { return true; }
900
901        public isPrivate() { return hasFlag(this.varFlags, VarFlags.Private); }
902        public isPublic() { return hasFlag(this.varFlags, VarFlags.Public); }
903        public isProperty() { return hasFlag(this.varFlags, VarFlags.Property); }
904
905        public typeCheck(typeFlow: TypeFlow) {
906            return typeFlow.typeCheckBoundDecl(this);
907        }
908
909        public printLabel() {
910            return this.treeViewLabel();
911        }
912    }
913
914    export class VarDecl extends BoundDecl {
915        constructor (id: Identifier, nest: number) {
916            super(id, NodeType.VarDecl, nest);
917        }
918
919        public isAmbient() { return hasFlag(this.varFlags, VarFlags.Ambient); }
920        public isExported() { return hasFlag(this.varFlags, VarFlags.Exported); }
921        public isStatic() { return hasFlag(this.varFlags, VarFlags.Static); }
922
923        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
924            emitter.emitJavascriptVarDecl(this, tokenId);
925        }
926
927        public treeViewLabel() {
928            return "var " + this.id.actualText;
929        }
930    }
931
932    export class ArgDecl extends BoundDecl {
933        constructor (id: Identifier) {
934            super(id, NodeType.ArgDecl, 0);
935        }
936
937        public isOptional = false;
938
939        public isOptionalArg() { return this.isOptional || this.init; }
940
941        public treeViewLabel() {
942            return "arg: " + this.id.actualText;
943        }
944
945        public parameterPropertySym: FieldSymbol = null;
946
947        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
948            emitter.emitParensAndCommentsInPlace(this, true);
949            emitter.recordSourceMappingStart(this);
950            emitter.writeToOutput(this.id.actualText);
951            emitter.recordSourceMappingEnd(this);
952            emitter.emitParensAndCommentsInPlace(this, false);
953        }
954    }
955
956    var internalId = 0;
957
958    export class FuncDecl extends AST {
959        public hint: string = null;
960        public fncFlags = FncFlags.None;
961        public returnTypeAnnotation: AST = null;
962        public symbols: IHashTable;
963        public variableArgList = false;
964        public signature: Signature;
965        public envids: Identifier[];
966        public jumpRefs: Identifier[] = null;
967        public internalNameCache: string = null;
968        public tmp1Declared = false;
969        public enclosingFnc: FuncDecl = null;
970        public freeVariables: Symbol[] = [];
971        public unitIndex = -1;
972        public classDecl: NamedDeclaration = null;
973        public boundToProperty: VarDecl = null;
974        public isOverload = false;
975        public innerStaticFuncs: FuncDecl[] = [];
976        public isTargetTypedAsMethod = false;
977        public isInlineCallLiteral = false;
978        public accessorSymbol: Symbol = null;
979        public leftCurlyCount = 0;
980        public rightCurlyCount = 0;
981        public returnStatementsWithExpressions: ReturnStatement[] = [];
982        public scopeType: Type = null; // Type of the FuncDecl, before target typing
983        public endingToken: ASTSpan = null;
984
985        constructor (public name: Identifier, public bod: ASTList, public isConstructor: boolean,
986                     public arguments: ASTList, public vars: ASTList, public scopes: ASTList, public statics: ASTList,
987            nodeType: number) {
988
989            super(nodeType);
990        }
991
992        public internalName(): string {
993            if (this.internalNameCache == null) {
994                var extName = this.getNameText();
995                if (extName) {
996                    this.internalNameCache = "_internal_" + extName;
997                }
998                else {
999                    this.internalNameCache = "_internal_" + internalId++;
1000                }
1001            }
1002            return this.internalNameCache;
1003        }
1004
1005        public hasSelfReference() { return hasFlag(this.fncFlags, FncFlags.HasSelfReference); }
1006        public setHasSelfReference() { this.fncFlags |= FncFlags.HasSelfReference; }
1007
1008        public addCloRef(id: Identifier, sym: Symbol): number {
1009            if (this.envids == null) {
1010                this.envids = new Identifier[];
1011            }
1012            this.envids[this.envids.length] = id;
1013            var outerFnc = this.enclosingFnc;
1014            if (sym) {
1015                while (outerFnc && (outerFnc.type.symbol != sym.container)) {
1016                    outerFnc.addJumpRef(sym);
1017                    outerFnc = outerFnc.enclosingFnc;
1018                }
1019            }
1020            return this.envids.length - 1;
1021        }
1022
1023        public addJumpRef(sym: Symbol): void {
1024            if (this.jumpRefs == null) {
1025                this.jumpRefs = new Identifier[];
1026            }
1027            var id = new Identifier(sym.name);
1028            this.jumpRefs[this.jumpRefs.length] = id;
1029            id.sym = sym;
1030            id.cloId = this.addCloRef(id, null);
1031        }
1032
1033        public buildControlFlow(): ControlFlowContext {
1034            var entry = new BasicBlock();
1035            var exit = new BasicBlock();
1036
1037            var context = new ControlFlowContext(entry, exit);
1038
1039            var controlFlowPrefix = (ast: AST, parent: AST, walker: IAstWalker) => {
1040                ast.addToControlFlow(walker.state);
1041                return ast;
1042            }
1043
1044            var walker = getAstWalkerFactory().getWalker(controlFlowPrefix, null, null, context);
1045            context.walker = walker;
1046            walker.walk(this.bod, this);
1047
1048            return context;
1049        }
1050
1051        public typeCheck(typeFlow: TypeFlow) {
1052            return typeFlow.typeCheckFunction(this);
1053        }
1054
1055        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1056            emitter.emitJavascriptFunction(this);
1057        }
1058
1059        public getNameText() {
1060            if (this.name) {
1061                return this.name.actualText;
1062            }
1063            else {
1064                return this.hint;
1065            }
1066        }
1067
1068        public isMethod() {
1069            return (this.fncFlags & FncFlags.Method) != FncFlags.None;
1070        }
1071
1072        public isCallMember() { return hasFlag(this.fncFlags, FncFlags.CallMember); }
1073        public isConstructMember() { return hasFlag(this.fncFlags, FncFlags.ConstructMember); }
1074        public isIndexerMember() { return hasFlag(this.fncFlags, FncFlags.IndexerMember); }
1075        public isSpecialFn() { return this.isCallMember() || this.isIndexerMember() || this.isConstructMember(); }
1076        public isAnonymousFn() { return this.name === null; }
1077        public isAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor) || hasFlag(this.fncFlags, FncFlags.SetAccessor); }
1078        public isGetAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor); }
1079        public isSetAccessor() { return hasFlag(this.fncFlags, FncFlags.SetAccessor); }
1080        public isAmbient() { return hasFlag(this.fncFlags, FncFlags.Ambient); }
1081        public isExported() { return hasFlag(this.fncFlags, FncFlags.Exported); }
1082        public isPrivate() { return hasFlag(this.fncFlags, FncFlags.Private); }
1083        public isPublic() { return hasFlag(this.fncFlags, FncFlags.Public); }
1084        public isStatic() { return hasFlag(this.fncFlags, FncFlags.Static); }
1085
1086        public treeViewLabel() {
1087            if (this.name == null) {
1088                return "funcExpr";
1089            }
1090            else {
1091                return "func: " + this.name.actualText
1092            }
1093        }
1094
1095        public ClearFlags(): void {
1096            this.fncFlags = FncFlags.None;
1097        }
1098
1099        public isSignature() { return (this.fncFlags & FncFlags.Signature) != FncFlags.None; }
1100
1101        public hasStaticDeclarations() { return (!this.isConstructor && (this.statics.members.length > 0 || this.innerStaticFuncs.length > 0)); }
1102    }
1103
1104    export class LocationInfo {
1105        constructor (public filename: string, public lineMap: number[], public unitIndex) { }
1106    }
1107
1108    export var unknownLocationInfo = new LocationInfo("unknown", null, -1);
1109
1110    export class Script extends FuncDecl {
1111        public locationInfo: LocationInfo = null;
1112        public referencedFiles: IFileReference[] = [];
1113        public requiresGlobal = false;
1114        public requiresInherits = false;
1115        public isResident = false;
1116        public isDeclareFile = false;
1117        public hasBeenTypeChecked = false;
1118        public topLevelMod: ModuleDeclaration = null;
1119        public leftCurlyCount = 0;
1120        public rightCurlyCount = 0;
1121        public vars: ASTList;
1122        public scopes: ASTList;
1123        // Remember if the script contains Unicode chars, that is needed when generating code for this script object to decide the output file correct encoding.
1124        public containsUnicodeChar = false;
1125        public containsUnicodeCharInComment = false;
1126
1127        constructor (vars: ASTList, scopes: ASTList) {
1128            super(new Identifier("script"), null, false, null, vars, scopes, null, NodeType.Script);
1129            this.vars = vars;
1130            this.scopes = scopes;
1131        }
1132
1133        public typeCheck(typeFlow: TypeFlow) {
1134            return typeFlow.typeCheckScript(this);
1135        }
1136
1137        public treeViewLabel() {
1138            return "Script";
1139        }
1140
1141        public emitRequired() {
1142            if (!this.isDeclareFile && !this.isResident && this.bod) {
1143                for (var i = 0, len = this.bod.members.length; i < len; i++) {
1144                    var stmt = this.bod.members[i];
1145                    if (stmt.nodeType == NodeType.ModuleDeclaration) {
1146                        if (!hasFlag((<ModuleDeclaration>stmt).modFlags, ModuleFlags.ShouldEmitModuleDecl | ModuleFlags.Ambient)) {
1147                            return true;
1148                        }
1149                    }
1150                    else if (stmt.nodeType == NodeType.ClassDeclaration) {
1151                        if (!hasFlag((<InterfaceDeclaration>stmt).varFlags, VarFlags.Ambient)) {
1152                            return true;
1153                        }
1154                    }
1155                    else if (stmt.nodeType == NodeType.VarDecl) {
1156                        if (!hasFlag((<VarDecl>stmt).varFlags, VarFlags.Ambient)) {
1157                            return true;
1158                        }
1159                    }
1160                    else if (stmt.nodeType == NodeType.FuncDecl) {
1161                        if (!(<FuncDecl>stmt).isSignature()) {
1162                            return true;
1163                        }
1164                    }
1165                    else if (stmt.nodeType != NodeType.InterfaceDeclaration && stmt.nodeType != NodeType.Empty) {
1166                        return true;
1167                    }
1168                }
1169            }
1170            return false;
1171        }
1172
1173        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1174            if (this.emitRequired()) {
1175                emitter.emitParensAndCommentsInPlace(this, true);
1176                emitter.recordSourceMappingStart(this);
1177                emitter.emitJavascriptList(this.bod, null, TokenID.Semicolon, true, false, false, true, this.requiresInherits);
1178                emitter.recordSourceMappingEnd(this);
1179                emitter.emitParensAndCommentsInPlace(this, false);
1180            }
1181        }
1182    }
1183
1184    export class NamedDeclaration extends ModuleElement {
1185        public leftCurlyCount = 0;
1186        public rightCurlyCount = 0;
1187
1188        constructor (nodeType: NodeType,
1189                     public name: Identifier,
1190                     public members: ASTList) {
1191            super(nodeType);
1192        }
1193    }
1194
1195    export class ModuleDeclaration extends NamedDeclaration {
1196        public modFlags = ModuleFlags.ShouldEmitModuleDecl;
1197        public mod: ModuleType;
1198        public prettyName: string;
1199        public amdDependencies: string[] = [];
1200        public vars: ASTList;
1201        public scopes: ASTList;
1202        // Remember if the module contains Unicode chars, that is needed for dynamic module as we will generate a file for each.
1203        public containsUnicodeChar = false;
1204        public containsUnicodeCharInComment = false;
1205
1206        constructor (name: Identifier, members: ASTList, vars: ASTList, scopes: ASTList, public endingToken: ASTSpan) {
1207            super(NodeType.ModuleDeclaration, name, members);
1208
1209            this.vars = vars;
1210            this.scopes = scopes;
1211            this.prettyName = this.name.actualText;
1212        }
1213
1214        public isExported() { return hasFlag(this.modFlags, ModuleFlags.Exported); }
1215        public isAmbient() { return hasFlag(this.modFlags, ModuleFlags.Ambient); }
1216        public isEnum() { return hasFlag(this.modFlags, ModuleFlags.IsEnum); }
1217
1218        public recordNonInterface() {
1219            this.modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;
1220        }
1221
1222        public typeCheck(typeFlow: TypeFlow) {
1223            return typeFlow.typeCheckModule(this);
1224        }
1225
1226        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1227            if (!hasFlag(this.modFlags, ModuleFlags.ShouldEmitModuleDecl)) {
1228                emitter.emitParensAndCommentsInPlace(this, true);
1229                emitter.recordSourceMappingStart(this);
1230                emitter.emitJavascriptModule(this);
1231                emitter.recordSourceMappingEnd(this);
1232                emitter.emitParensAndCommentsInPlace(this, false);
1233            }
1234        }
1235    }
1236
1237    export class TypeDeclaration extends NamedDeclaration {
1238        public varFlags = VarFlags.None;
1239
1240        constructor (nodeType: NodeType,
1241                     name: Identifier,
1242                     public extendsList: ASTList,
1243                     public implementsList: ASTList,
1244                     members: ASTList) {
1245            super(nodeType, name, members);
1246        }
1247
1248        public isExported() {
1249            return hasFlag(this.varFlags, VarFlags.Exported);
1250        }
1251
1252        public isAmbient() {
1253            return hasFlag(this.varFlags, VarFlags.Ambient);
1254        }
1255    }
1256
1257    export class ClassDeclaration extends TypeDeclaration {
1258        public knownMemberNames: any = {};
1259        public constructorDecl: FuncDecl = null;
1260        public constructorNestingLevel = 0;
1261        public endingToken: ASTSpan = null;
1262
1263        constructor (name: Identifier,
1264                     members: ASTList,
1265                     extendsList: ASTList,
1266                     implementsList: ASTList) {
1267            super(NodeType.ClassDeclaration, name, extendsList, implementsList, members);
1268        }
1269
1270        public typeCheck(typeFlow: TypeFlow) {
1271            return typeFlow.typeCheckClass(this);
1272        }
1273
1274        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1275            emitter.emitJavascriptClass(this);
1276        }
1277    }
1278
1279    export class InterfaceDeclaration extends TypeDeclaration {
1280        constructor (name: Identifier,
1281                     members: ASTList,
1282                     extendsList: ASTList,
1283                     implementsList: ASTList) {
1284            super(NodeType.InterfaceDeclaration, name, extendsList, implementsList, members);
1285        }
1286
1287        public typeCheck(typeFlow: TypeFlow) {
1288            return typeFlow.typeCheckInterface(this);
1289        }
1290
1291        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1292        }
1293    }
1294
1295    export class Statement extends ModuleElement {
1296        constructor (nodeType: NodeType) {
1297            super(nodeType);
1298            this.flags |= ASTFlags.IsStatement;
1299        }
1300
1301        public isLoop() { return false; }
1302
1303        public isStatementOrExpression() { return true; }
1304
1305        public isCompoundStatement() { return this.isLoop(); }
1306
1307        public typeCheck(typeFlow: TypeFlow) {
1308            this.type = typeFlow.voidType;
1309            return this;
1310        }
1311    }
1312
1313    export class LabeledStatement extends Statement {
1314        constructor (public labels: ASTList, public stmt: AST) {
1315            super(NodeType.LabeledStatement);
1316        }
1317
1318        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1319            emitter.emitParensAndCommentsInPlace(this, true);
1320            emitter.recordSourceMappingStart(this);
1321            if (this.labels) {
1322                var labelsLen = this.labels.members.length;
1323                for (var i = 0; i < labelsLen; i++) {
1324                    this.labels.members[i].emit(emitter, tokenId, startLine);
1325                }
1326            }
1327            this.stmt.emit(emitter, tokenId, true);
1328            emitter.recordSourceMappingEnd(this);
1329            emitter.emitParensAndCommentsInPlace(this, false);
1330        }
1331
1332        public typeCheck(typeFlow: TypeFlow) {
1333            typeFlow.typeCheck(this.labels);
1334            this.stmt = this.stmt.typeCheck(typeFlow);
1335            return this;
1336        }
1337
1338        public addToControlFlow(context: ControlFlowContext): void {
1339            var beforeBB = context.current;
1340            var bb = new BasicBlock();
1341            context.current = bb;
1342            beforeBB.addSuccessor(bb);
1343        }
1344    }
1345
1346    export class Block extends Statement {
1347        constructor (public statements: ASTList,
1348                     public isStatementBlock: boolean) {
1349            super(NodeType.Block);
1350        }
1351
1352        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1353            emitter.emitParensAndCommentsInPlace(this, true);
1354            emitter.recordSourceMappingStart(this);
1355            if (this.isStatementBlock) {
1356                emitter.writeLineToOutput(" {");
1357                emitter.indenter.increaseIndent();
1358            } else {
1359                emitter.setInVarBlock(this.statements.members.length);
1360            }
1361            var temp = emitter.setInObjectLiteral(false);
1362            if (this.statements) {
1363                emitter.emitJavascriptList(this.statements, null, TokenID.Semicolon, true, false, false);
1364            }
1365            if (this.isStatementBlock) {
1366                emitter.indenter.decreaseIndent();
1367                emitter.emitIndent();
1368                emitter.writeToOutput("}");
1369            }
1370            emitter.setInObjectLiteral(temp);
1371            emitter.recordSourceMappingEnd(this);
1372            emitter.emitParensAndCommentsInPlace(this, false);
1373        }
1374
1375        public addToControlFlow(context: ControlFlowContext) {
1376            var afterIfNeeded = new BasicBlock();
1377            context.pushStatement(this, context.current, afterIfNeeded);
1378            if (this.statements) {
1379                context.walk(this.statements, this);
1380            }
1381            context.walker.options.goChildren = false;
1382            context.popStatement();
1383            if (afterIfNeeded.predecessors.length > 0) {
1384                context.current.addSuccessor(afterIfNeeded);
1385                context.current = afterIfNeeded;
1386            }
1387        }
1388
1389        public typeCheck(typeFlow: TypeFlow) {
1390            if (!typeFlow.checker.styleSettings.emptyBlocks) {
1391                if ((this.statements === null) || (this.statements.members.length == 0)) {
1392                    typeFlow.checker.errorReporter.styleError(this, "empty block");
1393                }
1394            }
1395
1396            typeFlow.typeCheck(this.statements);
1397            return this;
1398        }
1399    }
1400
1401    export class Jump extends Statement {
1402        public target: string = null;
1403        public hasExplicitTarget() { return (this.target); }
1404        public resolvedTarget: Statement = null;
1405
1406        constructor (nodeType: NodeType) {
1407            super(nodeType);
1408        }
1409
1410        public setResolvedTarget(parser: Parser, stmt: Statement): boolean {
1411            if (stmt.isLoop()) {
1412                this.resolvedTarget = stmt;
1413                return true;
1414            }
1415            if (this.nodeType === NodeType.Continue) {
1416                parser.reportParseError("continue statement applies only to loops");
1417                return false;
1418            }
1419            else {
1420                if ((stmt.nodeType == NodeType.Switch) || this.hasExplicitTarget()) {
1421                    this.resolvedTarget = stmt;
1422                    return true;
1423                }
1424                else {
1425                    parser.reportParseError("break statement with no label can apply only to a loop or switch statement");
1426                    return false;
1427                }
1428            }
1429        }
1430
1431        public addToControlFlow(context: ControlFlowContext): void {
1432            super.addToControlFlow(context);
1433            context.unconditionalBranch(this.resolvedTarget, (this.nodeType == NodeType.Continue));
1434        }
1435
1436        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1437            emitter.emitParensAndCommentsInPlace(this, true);
1438            emitter.recordSourceMappingStart(this);
1439            if (this.nodeType == NodeType.Break) {
1440                emitter.writeToOutput("break");
1441            }
1442            else {
1443                emitter.writeToOutput("continue");
1444            }
1445            if (this.hasExplicitTarget()) {
1446                emitter.writeToOutput(" " + this.target);
1447            }
1448            emitter.recordSourceMappingEnd(this);
1449            emitter.writeToOutput(";");
1450            emitter.emitParensAndCommentsInPlace(this, false);
1451        }
1452    }
1453
1454    export class WhileStatement extends Statement {
1455        public body: AST = null;
1456
1457        constructor (public cond: AST) {
1458            super(NodeType.While);
1459        }
1460
1461        public isLoop() { return true; }
1462
1463        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1464            emitter.emitParensAndCommentsInPlace(this, true);
1465            emitter.recordSourceMappingStart(this);
1466            var temp = emitter.setInObjectLiteral(false);
1467            emitter.writeToOutput("while(");
1468            emitter.emitJavascript(this.cond, TokenID.While, false);
1469            emitter.writeToOutput(")");
1470            emitter.emitJavascriptStatements(this.body, false, false);
1471            emitter.setInObjectLiteral(temp);
1472            emitter.recordSourceMappingEnd(this);
1473            emitter.emitParensAndCommentsInPlace(this, false);
1474        }
1475
1476        public typeCheck(typeFlow: TypeFlow) {
1477            return typeFlow.typeCheckWhile(this);
1478        }
1479
1480        public addToControlFlow(context: ControlFlowContext): void {
1481            var loopHeader = context.current;
1482            var loopStart = new BasicBlock();
1483            var afterLoop = new BasicBlock();
1484
1485            loopHeader.addSuccessor(loopStart);
1486            context.current = loopStart;
1487            context.addContent(this.cond);
1488            var condBlock = context.current;
1489            var targetInfo: ITargetInfo = null;
1490            if (this.body) {
1491                context.current = new BasicBlock();
1492                condBlock.addSuccessor(context.current);
1493                context.pushStatement(this, loopStart, afterLoop);
1494                context.walk(this.body, this);
1495                targetInfo = context.popStatement();
1496            }
1497            if (!(context.noContinuation)) {
1498                var loopEnd = context.current;
1499                loopEnd.addSuccessor(loopStart);
1500            }
1501            context.current = afterLoop;
1502            condBlock.addSuccessor(afterLoop);
1503            // TODO: check for while (true) and then only continue if afterLoop has predecessors
1504            context.noContinuation = false;
1505            context.walker.options.goChildren = false;
1506        }
1507    }
1508
1509    export class DoWhileStatement extends Statement {
1510        public body: AST = null;
1511        public whileAST: AST = null;
1512        public cond: AST = null;
1513        public isLoop() { return true; }
1514
1515        constructor () {
1516            super(NodeType.DoWhile);
1517        }
1518
1519        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1520            emitter.emitParensAndCommentsInPlace(this, true);
1521            emitter.recordSourceMappingStart(this);
1522            var temp = emitter.setInObjectLiteral(false);
1523            emitter.writeToOutput("do");
1524            emitter.emitJavascriptStatements(this.body, true, false);
1525            emitter.recordSourceMappingStart(this.whileAST);
1526            emitter.writeToOutput("while");
1527            emitter.recordSourceMappingEnd(this.whileAST);
1528            emitter.writeToOutput('(');
1529            emitter.emitJavascript(this.cond, TokenID.CloseParen, false);
1530            emitter.writeToOutput(")");
1531            emitter.setInObjectLiteral(temp);
1532            emitter.recordSourceMappingEnd(this);
1533            emitter.emitParensAndCommentsInPlace(this, false);
1534        }
1535
1536        public typeCheck(typeFlow: TypeFlow) {
1537            return typeFlow.typeCheckDoWhile(this);
1538        }
1539
1540        public addToControlFlow(context: ControlFlowContext): void {
1541            var loopHeader = context.current;
1542            var loopStart = new BasicBlock();
1543            var afterLoop = new BasicBlock();
1544            loopHeader.addSuccessor(loopStart);
1545            context.current = loopStart;
1546            var targetInfo: ITargetInfo = null;
1547            if (this.body) {
1548                context.pushStatement(this, loopStart, afterLoop);
1549                context.walk(this.body, this);
1550                targetInfo = context.popStatement();
1551            }
1552            if (!(context.noContinuation)) {
1553                var loopEnd = context.current;
1554                loopEnd.addSuccessor(loopStart);
1555                context.addContent(this.cond);
1556                // TODO: check for while (true)
1557                context.current = afterLoop;
1558                loopEnd.addSuccessor(afterLoop);
1559            }
1560            else {
1561                context.addUnreachable(this.cond);
1562            }
1563            context.walker.options.goChildren = false;
1564        }
1565    }
1566
1567    export class IfStatement extends Statement {
1568        public thenBod: AST;
1569        public elseBod: AST = null;
1570        public statement: ASTSpan = new ASTSpan();
1571
1572        constructor (public cond: AST) {
1573            super(NodeType.If);
1574        }
1575
1576        public isCompoundStatement() { return true; }
1577
1578        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1579            emitter.emitParensAndCommentsInPlace(this, true);
1580            emitter.recordSourceMappingStart(this);
1581            var temp = emitter.setInObjectLiteral(false);
1582            emitter.recordSourceMappingStart(this.statement);
1583            emitter.writeToOutput("if(");
1584            emitter.emitJavascript(this.cond, TokenID.If, false);
1585            emitter.writeToOutput(")");
1586            emitter.recordSourceMappingEnd(this.statement);
1587            emitter.emitJavascriptStatements(this.thenBod, true, false);
1588            if (this.elseBod) {
1589                emitter.writeToOutput(" else");
1590                emitter.emitJavascriptStatements(this.elseBod, true, true);
1591            }
1592            emitter.setInObjectLiteral(temp);
1593            emitter.recordSourceMappingEnd(this);
1594            emitter.emitParensAndCommentsInPlace(this, false);
1595        }
1596
1597        public typeCheck(typeFlow: TypeFlow) {
1598            return typeFlow.typeCheckIf(this);
1599        }
1600
1601        public addToControlFlow(context: ControlFlowContext): void {
1602            this.cond.addToControlFlow(context);
1603            var afterIf = new BasicBlock();
1604            var beforeIf = context.current;
1605            context.pushStatement(this, beforeIf, afterIf);
1606            var hasContinuation = false;
1607            context.current = new BasicBlock();
1608            beforeIf.addSuccessor(context.current);
1609            context.walk(this.thenBod, this);
1610            if (!context.noContinuation) {
1611                hasContinuation = true;
1612                context.current.addSuccessor(afterIf);
1613            }
1614            if (this.elseBod) {
1615                // current block will be thenBod
1616                context.current = new BasicBlock();
1617                context.noContinuation = false;
1618                beforeIf.addSuccessor(context.current);
1619                context.walk(this.elseBod, this);
1620                if (!context.noContinuation) {
1621                    hasContinuation = true;
1622                    context.current.addSuccessor(afterIf);
1623                }
1624                else {
1625                    // thenBod created continuation for if statement
1626                    if (hasContinuation) {
1627                        context.noContinuation = false;
1628                    }
1629                }
1630            }
1631            else {
1632                beforeIf.addSuccessor(afterIf);
1633                context.noContinuation = false;
1634                hasContinuation = true;
1635            }
1636            var targetInfo = context.popStatement();
1637            if (afterIf.predecessors.length > 0) {
1638                context.noContinuation = false;
1639                hasContinuation = true;
1640            }
1641            if (hasContinuation) {
1642                context.current = afterIf;
1643            }
1644            context.walker.options.goChildren = false;
1645        }
1646    }
1647
1648    export class ReturnStatement extends Statement {
1649        public returnExpression: AST = null;
1650
1651        constructor () {
1652            super(NodeType.Return);
1653        }
1654
1655        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1656            emitter.emitParensAndCommentsInPlace(this, true);
1657            emitter.recordSourceMappingStart(this);
1658            var temp = emitter.setInObjectLiteral(false);
1659            if (this.returnExpression) {
1660                emitter.writeToOutput("return ");
1661                emitter.emitJavascript(this.returnExpression, TokenID.Semicolon, false);
1662            }
1663            else {
1664                emitter.writeToOutput("return;");
1665            }
1666            emitter.setInObjectLiteral(temp);
1667            emitter.recordSourceMappingEnd(this);
1668            emitter.emitParensAndCommentsInPlace(this, false);
1669        }
1670
1671        public addToControlFlow(context: ControlFlowContext): void {
1672            super.addToControlFlow(context);
1673            context.returnStmt();
1674        }
1675
1676        public typeCheck(typeFlow: TypeFlow) {
1677            return typeFlow.typeCheckReturn(this);
1678        }
1679    }
1680
1681    export class EndCode extends AST {
1682        constructor () {
1683            super(NodeType.EndCode);
1684        }
1685    }
1686
1687    export class ForInStatement extends Statement {
1688        constructor (public lval: AST, public obj: AST) {
1689            super(NodeType.ForIn);
1690            if (this.lval && (this.lval.nodeType == NodeType.VarDecl)) {
1691                (<BoundDecl>this.lval).varFlags |= VarFlags.AutoInit;
1692            }
1693        }
1694        public statement: ASTSpan = new ASTSpan();
1695        public body: AST;
1696
1697        public isLoop() { return true; }
1698
1699        public isFiltered() {
1700            if (this.body) {
1701                var singleItem: AST = null;
1702                if (this.body.nodeType == NodeType.List) {
1703                    var stmts = <ASTList>this.body;
1704                    if (stmts.members.length == 1) {
1705                        singleItem = stmts.members[0];
1706                    }
1707                }
1708                else {
1709                    singleItem = this.body;
1710                }
1711                // match template for filtering 'own' properties from obj
1712                if (singleItem !== null) {
1713                    if (singleItem.nodeType == NodeType.Block) {
1714                        var block = <Block>singleItem;
1715                        if ((block.statements !== null) && (block.statements.members.length == 1)) {
1716                            singleItem = block.statements.members[0];
1717                        }
1718                    }
1719                    if (singleItem.nodeType == NodeType.If) {
1720                        var cond = (<IfStatement>singleItem).cond;
1721                        if (cond.nodeType == NodeType.Call) {
1722                            var target = (<CallExpression>cond).target;
1723                            if (target.nodeType == NodeType.Dot) {
1724                                var binex = <BinaryExpression>target;
1725                                if ((binex.operand1.nodeType == NodeType.Name) &&
1726                                    (this.obj.nodeType == NodeType.Name) &&
1727                                    ((<Identifier>binex.operand1).actualText == (<Identifier>this.obj).actualText)) {
1728                                    var prop = <Identifier>binex.operand2;
1729                                    if (prop.actualText == "hasOwnProperty") {
1730                                        var args = (<CallExpression>cond).arguments;
1731                                        if ((args !== null) && (args.members.length == 1)) {
1732                                            var arg = args.members[0];
1733                                            if ((arg.nodeType == NodeType.Name) &&
1734                                                 (this.lval.nodeType == NodeType.Name)) {
1735                                                if (((<Identifier>this.lval).actualText) == (<Identifier>arg).actualText) {
1736                                                    return true;
1737                                                }
1738                                            }
1739                                        }
1740                                    }
1741                                }
1742                            }
1743                        }
1744                    }
1745                }
1746            }
1747            return false;
1748        }
1749
1750        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1751            emitter.emitParensAndCommentsInPlace(this, true);
1752            emitter.recordSourceMappingStart(this);
1753            var temp = emitter.setInObjectLiteral(false);
1754            emitter.recordSourceMappingStart(this.statement);
1755            emitter.writeToOutput("for(");
1756            emitter.emitJavascript(this.lval, TokenID.For, false);
1757            emitter.writeToOutput(" in ");
1758            emitter.emitJavascript(this.obj, TokenID.For, false);
1759            emitter.writeToOutput(")");
1760            emitter.recordSourceMappingEnd(this.statement);
1761            emitter.emitJavascriptStatements(this.body, true, false);
1762            emitter.setInObjectLiteral(temp);
1763            emitter.recordSourceMappingEnd(this);
1764            emitter.emitParensAndCommentsInPlace(this, false);
1765        }
1766
1767        public typeCheck(typeFlow: TypeFlow) {
1768            if (typeFlow.checker.styleSettings.forin) {
1769                if (!this.isFiltered()) {
1770                    typeFlow.checker.errorReporter.styleError(this, "no hasOwnProperty filter");
1771                }
1772            }
1773            return typeFlow.typeCheckForIn(this);
1774        }
1775
1776        public addToControlFlow(context: ControlFlowContext): void {
1777            if (this.lval) {
1778                context.addContent(this.lval);
1779            }
1780            if (this.obj) {
1781                context.addContent(this.obj);
1782            }
1783
1784            var loopHeader = context.current;
1785            var loopStart = new BasicBlock();
1786            var afterLoop = new BasicBlock();
1787
1788            loopHeader.addSuccessor(loopStart);
1789            context.current = loopStart;
1790            if (this.body) {
1791                context.pushStatement(this, loopStart, afterLoop);
1792                context.walk(this.body, this);
1793                context.popStatement();
1794            }
1795            if (!(context.noContinuation)) {
1796                var loopEnd = context.current;
1797                loopEnd.addSuccessor(loopStart);
1798            }
1799            context.current = afterLoop;
1800            context.noContinuation = false;
1801            loopHeader.addSuccessor(afterLoop);
1802            context.walker.options.goChildren = false;
1803        }
1804    }
1805
1806    export class ForStatement extends Statement {
1807        public cond: AST;
1808        public body: AST;
1809        public incr: AST;
1810
1811        constructor (public init: AST) {
1812            super(NodeType.For);
1813        }
1814
1815        public isLoop() { return true; }
1816
1817        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1818            emitter.emitParensAndCommentsInPlace(this, true);
1819            emitter.recordSourceMappingStart(this);
1820            var temp = emitter.setInObjectLiteral(false);
1821            emitter.writeToOutput("for(");
1822            if (this.init) {
1823                if (this.init.nodeType != NodeType.List) {
1824                    emitter.emitJavascript(this.init, TokenID.For, false);
1825                }
1826                else {
1827                    emitter.setInVarBlock((<ASTList>this.init).members.length);
1828                    emitter.emitJavascriptList(this.init, null, TokenID.For, false, false, false);
1829                }
1830            }
1831            emitter.writeToOutput("; ");
1832            emitter.emitJavascript(this.cond, TokenID.For, false);
1833            emitter.writeToOutput("; ");
1834            emitter.emitJavascript(this.incr, TokenID.For, false);
1835            emitter.writeToOutput(")");
1836            emitter.emitJavascriptStatements(this.body, true, false);
1837            emitter.setInObjectLiteral(temp);
1838            emitter.recordSourceMappingEnd(this);
1839            emitter.emitParensAndCommentsInPlace(this, false);
1840        }
1841
1842        public typeCheck(typeFlow: TypeFlow) {
1843            return typeFlow.typeCheckFor(this);
1844        }
1845
1846        public addToControlFlow(context: ControlFlowContext): void {
1847            if (this.init) {
1848                context.addContent(this.init);
1849            }
1850            var loopHeader = context.current;
1851            var loopStart = new BasicBlock();
1852            var afterLoop = new BasicBlock();
1853
1854            loopHeader.addSuccessor(loopStart);
1855            context.current = loopStart;
1856            var condBlock: BasicBlock = null;
1857            var continueTarget = loopStart;
1858            var incrBB: BasicBlock = null;
1859            if (this.incr) {
1860                incrBB = new BasicBlock();
1861                continueTarget = incrBB;
1862            }
1863            if (this.cond) {
1864                condBlock = context.current;
1865                context.addContent(this.cond);
1866                context.current = new BasicBlock();
1867                condBlock.addSuccessor(context.current);
1868            }
1869            var targetInfo: ITargetInfo = null;
1870            if (this.body) {
1871                context.pushStatement(this, continueTarget, afterLoop);
1872                context.walk(this.body, this);
1873                targetInfo = context.popStatement();
1874            }
1875            if (this.incr) {
1876                if (context.noContinuation) {
1877                    if (incrBB.predecessors.length == 0) {
1878                        context.addUnreachable(this.incr);
1879                    }
1880                }
1881                else {
1882                    context.current.addSuccessor(incrBB);
1883                    context.current = incrBB;
1884                    context.addContent(this.incr);
1885                }
1886            }
1887            var loopEnd = context.current;
1888            if (!(context.noContinuation)) {
1889                loopEnd.addSuccessor(loopStart);
1890
1891            }
1892            if (condBlock) {
1893                condBlock.addSuccessor(afterLoop);
1894                context.noContinuation = false;
1895            }
1896            if (afterLoop.predecessors.length > 0) {
1897                context.noContinuation = false;
1898                context.current = afterLoop;
1899            }
1900            context.walker.options.goChildren = false;
1901        }
1902    }
1903
1904    export class WithStatement extends Statement {
1905        public body: AST;
1906
1907        public isCompoundStatement() { return true; }
1908
1909        public withSym: WithSymbol = null;
1910
1911        constructor (public expr: AST) {
1912            super(NodeType.With);
1913        }
1914
1915        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1916            emitter.emitParensAndCommentsInPlace(this, true);
1917            emitter.recordSourceMappingStart(this);
1918            emitter.writeToOutput("with (");
1919            if (this.expr) {
1920                emitter.emitJavascript(this.expr, TokenID.With, false);
1921            }
1922
1923            emitter.writeToOutput(")");
1924            emitter.emitJavascriptStatements(this.body, true, false);
1925            emitter.recordSourceMappingEnd(this);
1926            emitter.emitParensAndCommentsInPlace(this, false);
1927        }
1928
1929        public typeCheck(typeFlow: TypeFlow) {
1930            return typeFlow.typeCheckWith(this);
1931        }
1932    }
1933
1934    export class SwitchStatement extends Statement {
1935        public caseList: ASTList;
1936        public defaultCase: CaseStatement = null;
1937        public statement: ASTSpan = new ASTSpan();
1938
1939        constructor (public val: AST) {
1940            super(NodeType.Switch);
1941        }
1942
1943        public isCompoundStatement() { return true; }
1944
1945        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
1946            emitter.emitParensAndCommentsInPlace(this, true);
1947            emitter.recordSourceMappingStart(this);
1948            var temp = emitter.setInObjectLiteral(false);
1949            emitter.recordSourceMappingStart(this.statement);
1950            emitter.writeToOutput("switch(");
1951            emitter.emitJavascript(this.val, TokenID.Identifier, false);
1952            emitter.writeToOutput(")");
1953            emitter.recordSourceMappingEnd(this.statement);
1954            emitter.writeLineToOutput(" {");
1955            emitter.indenter.increaseIndent();
1956            var casesLen = this.caseList.members.length;
1957            for (var i = 0; i < casesLen; i++) {
1958                var caseExpr = this.caseList.members[i];
1959                emitter.emitJavascript(caseExpr, TokenID.Case, true);
1960                emitter.writeLineToOutput("");
1961            }
1962            emitter.indenter.decreaseIndent();
1963            emitter.emitIndent();
1964            emitter.writeToOutput("}");
1965            emitter.setInObjectLiteral(temp);
1966            emitter.recordSourceMappingEnd(this);
1967            emitter.emitParensAndCommentsInPlace(this, false);
1968        }
1969
1970        public typeCheck(typeFlow: TypeFlow) {
1971            var len = this.caseList.members.length;
1972            this.val = typeFlow.typeCheck(this.val);
1973            for (var i = 0; i < len; i++) {
1974                this.caseList.members[i] = typeFlow.typeCheck(this.caseList.members[i]);
1975            }
1976            this.defaultCase = <CaseStatement>typeFlow.typeCheck(this.defaultCase);
1977            this.type = typeFlow.voidType;
1978            return this;
1979        }
1980
1981        // if there are break statements that match this switch, then just link cond block with block after switch
1982        public addToControlFlow(context: ControlFlowContext) {
1983            var condBlock = context.current;
1984            context.addContent(this.val);
1985            var execBlock = new BasicBlock();
1986            var afterSwitch = new BasicBlock();
1987
1988            condBlock.addSuccessor(execBlock);
1989            context.pushSwitch(execBlock);
1990            context.current = execBlock;
1991            context.pushStatement(this, execBlock, afterSwitch);
1992            context.walk(this.caseList, this);
1993            context.popSwitch();
1994            var targetInfo = context.popStatement();
1995            var hasCondContinuation = (this.defaultCase == null);
1996            if (this.defaultCase == null) {
1997                condBlock.addSuccessor(afterSwitch);
1998            }
1999            if (afterSwitch.predecessors.length > 0) {
2000                context.noContinuation = false;
2001                context.current = afterSwitch;
2002            }
2003            else {
2004                context.noContinuation = true;
2005            }
2006            context.walker.options.goChildren = false;
2007        }
2008    }
2009
2010    export class CaseStatement extends Statement {
2011        public expr: AST = null;
2012        public body: ASTList;
2013
2014        constructor () {
2015            super(NodeType.Case);
2016        }
2017
2018        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2019            emitter.emitParensAndCommentsInPlace(this, true);
2020            emitter.recordSourceMappingStart(this);
2021            if (this.expr) {
2022                emitter.writeToOutput("case ");
2023                emitter.emitJavascript(this.expr, TokenID.Identifier, false);
2024            }
2025            else {
2026                emitter.writeToOutput("default");
2027            }
2028            emitter.writeToOutput(":");
2029            emitter.emitJavascriptStatements(this.body, false, false);
2030            emitter.recordSourceMappingEnd(this);
2031            emitter.emitParensAndCommentsInPlace(this, false);
2032        }
2033
2034        public typeCheck(typeFlow: TypeFlow) {
2035            this.expr = typeFlow.typeCheck(this.expr);
2036            typeFlow.typeCheck(this.body);
2037            this.type = typeFlow.voidType;
2038            return this;
2039        }
2040
2041        // TODO: more reasoning about unreachable cases (such as duplicate literals as case expressions)
2042        // for now, assume all cases are reachable, regardless of whether some cases fall through
2043        public addToControlFlow(context: ControlFlowContext) {
2044            var execBlock = new BasicBlock();
2045            var sw = context.currentSwitch[context.currentSwitch.length - 1];
2046            // TODO: fall-through from previous (+ to end of switch)
2047            if (this.expr) {
2048                var exprBlock = new BasicBlock();
2049                context.current = exprBlock;
2050                sw.addSuccessor(exprBlock);
2051                context.addContent(this.expr);
2052                exprBlock.addSuccessor(execBlock);
2053            }
2054            else {
2055                sw.addSuccessor(execBlock);
2056            }
2057            context.current = execBlock;
2058            if (this.body) {
2059                context.walk(this.body, this);
2060            }
2061            context.noContinuation = false;
2062            context.walker.options.goChildren = false;
2063        }
2064    }
2065
2066    export class TypeReference extends AST {
2067        constructor (public term: AST, public arrayCount: number) {
2068            super(NodeType.TypeRef);
2069        }
2070
2071        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2072            throw new Error("should not emit a type ref");
2073        }
2074
2075        public typeCheck(typeFlow: TypeFlow) {
2076            var prevInTCTR = typeFlow.inTypeRefTypeCheck;
2077            typeFlow.inTypeRefTypeCheck = true;
2078            var typeLink = getTypeLink(this, typeFlow.checker, true);
2079            typeFlow.checker.resolveTypeLink(typeFlow.scope, typeLink, false);
2080
2081            if (this.term) {
2082                typeFlow.typeCheck(this.term);
2083            }
2084
2085            typeFlow.checkForVoidConstructor(typeLink.type, this);
2086
2087            this.type = typeLink.type;
2088
2089            // in error recovery cases, there may not be a term
2090            if (this.term) {
2091                this.term.type = this.type;
2092            }
2093
2094            typeFlow.inTypeRefTypeCheck = prevInTCTR;
2095            return this;
2096        }
2097    }
2098
2099    export class TryFinally extends Statement {
2100        constructor (public tryNode: AST, public finallyNode: Finally) {
2101            super(NodeType.TryFinally);
2102        }
2103
2104        public isCompoundStatement() { return true; }
2105
2106        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2107            emitter.recordSourceMappingStart(this);
2108            emitter.emitJavascript(this.tryNode, TokenID.Try, false);
2109            emitter.emitJavascript(this.finallyNode, TokenID.Finally, false);
2110            emitter.recordSourceMappingEnd(this);
2111        }
2112
2113        public typeCheck(typeFlow: TypeFlow) {
2114            this.tryNode = typeFlow.typeCheck(this.tryNode);
2115            this.finallyNode = <Finally>typeFlow.typeCheck(this.finallyNode);
2116            this.type = typeFlow.voidType;
2117            return this;
2118        }
2119
2120        public addToControlFlow(context: ControlFlowContext) {
2121            var afterFinally = new BasicBlock();
2122            context.walk(this.tryNode, this);
2123            var finBlock = new BasicBlock();
2124            if (context.current) {
2125                context.current.addSuccessor(finBlock);
2126            }
2127            context.current = finBlock;
2128            context.pushStatement(this, null, afterFinally);
2129            context.walk(this.finallyNode, this);
2130            if (!context.noContinuation && context.current) {
2131                context.current.addSuccessor(afterFinally);
2132            }
2133            if (afterFinally.predecessors.length > 0) {
2134                context.current = afterFinally;
2135            }
2136            else {
2137                context.noContinuation = true;
2138            }
2139            context.popStatement();
2140            context.walker.options.goChildren = false;
2141        }
2142    }
2143
2144    export class TryCatch extends Statement {
2145        constructor (public tryNode: Try, public catchNode: Catch) {
2146            super(NodeType.TryCatch);
2147        }
2148
2149        public isCompoundStatement() { return true; }
2150
2151        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2152            emitter.emitParensAndCommentsInPlace(this, true);
2153            emitter.recordSourceMappingStart(this);
2154            emitter.emitJavascript(this.tryNode, TokenID.Try, false);
2155            emitter.emitJavascript(this.catchNode, TokenID.Catch, false);
2156            emitter.recordSourceMappingEnd(this);
2157            emitter.emitParensAndCommentsInPlace(this, false);
2158        }
2159
2160        public addToControlFlow(context: ControlFlowContext) {
2161            var beforeTry = context.current;
2162            var tryBlock = new BasicBlock();
2163            beforeTry.addSuccessor(tryBlock);
2164            context.current = tryBlock;
2165            var afterTryCatch = new BasicBlock();
2166            context.pushStatement(this, null, afterTryCatch);
2167            context.walk(this.tryNode, this);
2168            if (!context.noContinuation) {
2169                if (context.current) {
2170                    context.current.addSuccessor(afterTryCatch);
2171                }
2172            }
2173            context.current = new BasicBlock();
2174            beforeTry.addSuccessor(context.current);
2175            context.walk(this.catchNode, this);
2176            context.popStatement();
2177            if (!context.noContinuation) {
2178                if (context.current) {
2179                    context.current.addSuccessor(afterTryCatch);
2180                }
2181            }
2182            context.current = afterTryCatch;
2183            context.walker.options.goChildren = false;
2184        }
2185
2186        public typeCheck(typeFlow: TypeFlow) {
2187            this.tryNode = <Try>typeFlow.typeCheck(this.tryNode);
2188            this.catchNode = <Catch>typeFlow.typeCheck(this.catchNode);
2189            this.type = typeFlow.voidType;
2190            return this;
2191        }
2192    }
2193
2194    export class Try extends Statement {
2195        constructor (public body: AST) {
2196            super(NodeType.Try);
2197        }
2198
2199        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2200            emitter.emitParensAndCommentsInPlace(this, true);
2201            emitter.recordSourceMappingStart(this);
2202            emitter.writeToOutput("try ");
2203            emitter.emitJavascript(this.body, TokenID.Try, false);
2204            emitter.recordSourceMappingEnd(this);
2205            emitter.emitParensAndCommentsInPlace(this, false);
2206        }
2207
2208        public typeCheck(typeFlow: TypeFlow) {
2209            this.body = typeFlow.typeCheck(this.body);
2210            return this;
2211        }
2212
2213        public addToControlFlow(context: ControlFlowContext) {
2214            if (this.body) {
2215                context.walk(this.body, this);
2216            }
2217            context.walker.options.goChildren = false;
2218            context.noContinuation = false;
2219        }
2220    }
2221
2222    export class Catch extends Statement {
2223        constructor (public param: VarDecl, public body: AST) {
2224            super(NodeType.Catch);
2225            if (this.param) {
2226                this.param.varFlags |= VarFlags.AutoInit;
2227            }
2228        }
2229        public statement: ASTSpan = new ASTSpan();
2230        public containedScope: SymbolScope = null;
2231
2232        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2233            emitter.emitParensAndCommentsInPlace(this, true);
2234            emitter.recordSourceMappingStart(this);
2235            emitter.writeToOutput(" ");
2236            emitter.recordSourceMappingStart(this.statement);
2237            emitter.writeToOutput("catch (");
2238            emitter.emitJavascript(this.param, TokenID.OpenParen, false);
2239            emitter.writeToOutput(")");
2240            emitter.recordSourceMappingEnd(this.statement);
2241            emitter.emitJavascript(this.body, TokenID.Catch, false);
2242            emitter.recordSourceMappingEnd(this);
2243            emitter.emitParensAndCommentsInPlace(this, false);
2244        }
2245
2246        public addToControlFlow(context: ControlFlowContext) {
2247            if (this.param) {
2248                context.addContent(this.param);
2249                var bodBlock = new BasicBlock();
2250                context.current.addSuccessor(bodBlock);
2251                context.current = bodBlock;
2252            }
2253            if (this.body) {
2254                context.walk(this.body, this);
2255            }
2256            context.noContinuation = false;
2257            context.walker.options.goChildren = false;
2258        }
2259
2260        public typeCheck(typeFlow: TypeFlow) {
2261            var prevScope = typeFlow.scope;
2262            typeFlow.scope = this.containedScope;
2263            this.param = <VarDecl>typeFlow.typeCheck(this.param);
2264            var exceptVar = new ValueLocation();
2265            var varSym = new VariableSymbol((<VarDecl>this.param).id.text,
2266                                          this.param.minChar,
2267                                          typeFlow.checker.locationInfo.unitIndex,
2268                                          exceptVar);
2269            exceptVar.symbol = varSym;
2270            exceptVar.typeLink = new TypeLink();
2271            // var type for now (add syntax for type annotation)
2272            exceptVar.typeLink.type = typeFlow.anyType;
2273            var thisFnc = typeFlow.thisFnc;
2274            if (thisFnc && thisFnc.type) {
2275                exceptVar.symbol.container = thisFnc.type.symbol;
2276            }
2277            else {
2278                exceptVar.symbol.container = null;
2279            }
2280            this.param.sym = exceptVar.symbol;
2281            typeFlow.scope.enter(exceptVar.symbol.container, this.param, exceptVar.symbol,
2282                                 typeFlow.checker.errorReporter, false, false, false);
2283            this.body = typeFlow.typeCheck(this.body);
2284
2285            // if we're in provisional typecheck mode, clean up the symbol entry
2286            // REVIEW: This is obviously bad form, since we're counting on the internal
2287            // layout of the symbol table, but this is also the only place where we insert
2288            // symbols during typecheck
2289            if (typeFlow.checker.inProvisionalTypecheckMode()) {
2290                var table = typeFlow.scope.getTable();
2291                (<any>table).secondaryTable.table[exceptVar.symbol.name] = undefined;
2292            }
2293            this.type = typeFlow.voidType;
2294            typeFlow.scope = prevScope;
2295            return this;
2296        }
2297    }
2298
2299    export class Finally extends Statement {
2300        constructor (public body: AST) {
2301            super(NodeType.Finally);
2302        }
2303
2304        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2305            emitter.emitParensAndCommentsInPlace(this, true);
2306            emitter.recordSourceMappingStart(this);
2307            emitter.writeToOutput("finally");
2308            emitter.emitJavascript(this.body, TokenID.Finally, false);
2309            emitter.recordSourceMappingEnd(this);
2310            emitter.emitParensAndCommentsInPlace(this, false);
2311        }
2312
2313        public addToControlFlow(context: ControlFlowContext) {
2314            if (this.body) {
2315                context.walk(this.body, this);
2316            }
2317            context.walker.options.goChildren = false;
2318            context.noContinuation = false;
2319        }
2320
2321        public typeCheck(typeFlow: TypeFlow) {
2322            this.body = typeFlow.typeCheck(this.body);
2323            return this;
2324        }
2325    }
2326
2327    export class Comment extends AST {
2328
2329        public text: string[] = null;
2330
2331        constructor (public content: string, public isBlockComment: boolean, public endsLine) {
2332            super(NodeType.Comment);
2333        }
2334
2335        public getText(): string[] {
2336            if (this.text == null) {
2337                if (this.isBlockComment) {
2338                    this.text = this.content.split("\n");
2339                    for (var i = 0; i < this.text.length; i++) {
2340                        this.text[i] = this.text[i].replace(/^\s+|\s+$/g, '');
2341                    }
2342                }
2343                else {
2344                    this.text = [(this.content.replace(/^\s+|\s+$/g, ''))];
2345                }
2346            }
2347
2348            return this.text;
2349        }
2350    }
2351
2352    export class DebuggerStatement extends Statement {
2353        constructor () {
2354            super(NodeType.Debugger);
2355        }
2356
2357        public emit(emitter: Emitter, tokenId: TokenID, startLine: boolean) {
2358            emitter.emitParensAndCommentsInPlace(this, true);
2359            emitter.recordSourceMappingStart(this);
2360            emitter.writeLineToOutput("debugger;");
2361            emitter.recordSourceMappingEnd(this);
2362            emitter.emitParensAndCommentsInPlace(this, false);
2363        }
2364    }
2365}
2366
2367//// [parserRealSource11.js]
2368// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
2369// See LICENSE.txt in the project root for complete license information.
2370var __extends = (this && this.__extends) || (function () {
2371    var extendStatics = function (d, b) {
2372        extendStatics = Object.setPrototypeOf ||
2373            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2374            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
2375        return extendStatics(d, b);
2376    };
2377    return function (d, b) {
2378        if (typeof b !== "function" && b !== null)
2379            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
2380        extendStatics(d, b);
2381        function __() { this.constructor = d; }
2382        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2383    };
2384})();
2385///<reference path='typescript.ts' />
2386var TypeScript;
2387(function (TypeScript) {
2388    var ASTSpan = /** @class */ (function () {
2389        function ASTSpan() {
2390            this.minChar = -1; // -1 = "undefined" or "compiler generated"
2391            this.limChar = -1; // -1 = "undefined" or "compiler generated"
2392        }
2393        return ASTSpan;
2394    }());
2395    TypeScript.ASTSpan = ASTSpan;
2396    var AST = /** @class */ (function (_super) {
2397        __extends(AST, _super);
2398        function AST(nodeType) {
2399            var _this = _super.call(this) || this;
2400            _this.nodeType = nodeType;
2401            _this.type = null;
2402            _this.flags = ASTFlags.Writeable;
2403            // REVIEW: for diagnostic purposes
2404            _this.passCreated = CompilerDiagnostics.analysisPass;
2405            _this.preComments = null;
2406            _this.postComments = null;
2407            _this.isParenthesized = false;
2408            return _this;
2409        }
2410        AST.prototype.isExpression = function () { return false; };
2411        AST.prototype.isStatementOrExpression = function () { return false; };
2412        AST.prototype.isCompoundStatement = function () { return false; };
2413        AST.prototype.isLeaf = function () { return this.isStatementOrExpression() && (!this.isCompoundStatement()); };
2414        AST.prototype.typeCheck = function (typeFlow) {
2415            switch (this.nodeType) {
2416                case NodeType.Error:
2417                case NodeType.EmptyExpr:
2418                    this.type = typeFlow.anyType;
2419                    break;
2420                case NodeType.This:
2421                    return typeFlow.typeCheckThis(this);
2422                case NodeType.Null:
2423                    this.type = typeFlow.nullType;
2424                    break;
2425                case NodeType.False:
2426                case NodeType.True:
2427                    this.type = typeFlow.booleanType;
2428                    break;
2429                case NodeType.Super:
2430                    return typeFlow.typeCheckSuper(this);
2431                case NodeType.EndCode:
2432                case NodeType.Empty:
2433                case NodeType.Void:
2434                    this.type = typeFlow.voidType;
2435                    break;
2436                default:
2437                    throw new Error("please implement in derived class");
2438            }
2439            return this;
2440        };
2441        AST.prototype.emit = function (emitter, tokenId, startLine) {
2442            emitter.emitParensAndCommentsInPlace(this, true);
2443            switch (this.nodeType) {
2444                case NodeType.This:
2445                    emitter.recordSourceMappingStart(this);
2446                    if (emitter.thisFnc && (hasFlag(emitter.thisFnc.fncFlags, FncFlags.IsFatArrowFunction))) {
2447                        emitter.writeToOutput("_this");
2448                    }
2449                    else {
2450                        emitter.writeToOutput("this");
2451                    }
2452                    emitter.recordSourceMappingEnd(this);
2453                    break;
2454                case NodeType.Null:
2455                    emitter.recordSourceMappingStart(this);
2456                    emitter.writeToOutput("null");
2457                    emitter.recordSourceMappingEnd(this);
2458                    break;
2459                case NodeType.False:
2460                    emitter.recordSourceMappingStart(this);
2461                    emitter.writeToOutput("false");
2462                    emitter.recordSourceMappingEnd(this);
2463                    break;
2464                case NodeType.True:
2465                    emitter.recordSourceMappingStart(this);
2466                    emitter.writeToOutput("true");
2467                    emitter.recordSourceMappingEnd(this);
2468                    break;
2469                case NodeType.Super:
2470                    emitter.recordSourceMappingStart(this);
2471                    emitter.emitSuperReference();
2472                    emitter.recordSourceMappingEnd(this);
2473                    break;
2474                case NodeType.EndCode:
2475                    break;
2476                case NodeType.Error:
2477                case NodeType.EmptyExpr:
2478                    break;
2479                case NodeType.Empty:
2480                    emitter.recordSourceMappingStart(this);
2481                    emitter.writeToOutput("; ");
2482                    emitter.recordSourceMappingEnd(this);
2483                    break;
2484                case NodeType.Void:
2485                    emitter.recordSourceMappingStart(this);
2486                    emitter.writeToOutput("void ");
2487                    emitter.recordSourceMappingEnd(this);
2488                    break;
2489                default:
2490                    throw new Error("please implement in derived class");
2491            }
2492            emitter.emitParensAndCommentsInPlace(this, false);
2493        };
2494        AST.prototype.print = function (context) {
2495            context.startLine();
2496            var lineCol = { line: -1, col: -1 };
2497            var limLineCol = { line: -1, col: -1 };
2498            if (context.parser !== null) {
2499                context.parser.getSourceLineCol(lineCol, this.minChar);
2500                context.parser.getSourceLineCol(limLineCol, this.limChar);
2501                context.write("(" + lineCol.line + "," + lineCol.col + ")--" +
2502                    "(" + limLineCol.line + "," + limLineCol.col + "): ");
2503            }
2504            var lab = this.printLabel();
2505            if (hasFlag(this.flags, ASTFlags.Error)) {
2506                lab += " (Error)";
2507            }
2508            context.writeLine(lab);
2509        };
2510        AST.prototype.printLabel = function () {
2511            if (nodeTypeTable[this.nodeType] !== undefined) {
2512                return nodeTypeTable[this.nodeType];
2513            }
2514            else {
2515                return NodeType._map[this.nodeType];
2516            }
2517        };
2518        AST.prototype.addToControlFlow = function (context) {
2519            // by default, AST adds itself to current basic block and does not check its children
2520            context.walker.options.goChildren = false;
2521            context.addContent(this);
2522        };
2523        AST.prototype.netFreeUses = function (container, freeUses) {
2524        };
2525        AST.prototype.treeViewLabel = function () {
2526            return NodeType._map[this.nodeType];
2527        };
2528        AST.getResolvedIdentifierName = function (name) {
2529            if (!name)
2530                return "";
2531            var resolved = "";
2532            var start = 0;
2533            var i = 0;
2534            while (i <= name.length - 6) {
2535                // Look for escape sequence \uxxxx
2536                if (name.charAt(i) == '\\' && name.charAt(i + 1) == 'u') {
2537                    var charCode = parseInt(name.substr(i + 2, 4), 16);
2538                    resolved += name.substr(start, i - start);
2539                    resolved += String.fromCharCode(charCode);
2540                    i += 6;
2541                    start = i;
2542                    continue;
2543                }
2544                i++;
2545            }
2546            // Append remaining string
2547            resolved += name.substring(start);
2548            return resolved;
2549        };
2550        return AST;
2551    }(ASTSpan));
2552    TypeScript.AST = AST;
2553    var IncompleteAST = /** @class */ (function (_super) {
2554        __extends(IncompleteAST, _super);
2555        function IncompleteAST(min, lim) {
2556            var _this = _super.call(this, NodeType.Error) || this;
2557            _this.minChar = min;
2558            _this.limChar = lim;
2559            return _this;
2560        }
2561        return IncompleteAST;
2562    }(AST));
2563    TypeScript.IncompleteAST = IncompleteAST;
2564    var ASTList = /** @class */ (function (_super) {
2565        __extends(ASTList, _super);
2566        function ASTList() {
2567            var _this = _super.call(this, NodeType.List) || this;
2568            _this.enclosingScope = null;
2569            _this.members = new AST[];
2570            return _this;
2571        }
2572        ASTList.prototype.addToControlFlow = function (context) {
2573            var len = this.members.length;
2574            for (var i = 0; i < len; i++) {
2575                if (context.noContinuation) {
2576                    context.addUnreachable(this.members[i]);
2577                    break;
2578                }
2579                else {
2580                    this.members[i] = context.walk(this.members[i], this);
2581                }
2582            }
2583            context.walker.options.goChildren = false;
2584        };
2585        ASTList.prototype.append = function (ast) {
2586            this.members[this.members.length] = ast;
2587            return this;
2588        };
2589        ASTList.prototype.appendAll = function (ast) {
2590            if (ast.nodeType == NodeType.List) {
2591                var list = ast;
2592                for (var i = 0, len = list.members.length; i < len; i++) {
2593                    this.append(list.members[i]);
2594                }
2595            }
2596            else {
2597                this.append(ast);
2598            }
2599            return this;
2600        };
2601        ASTList.prototype.emit = function (emitter, tokenId, startLine) {
2602            emitter.recordSourceMappingStart(this);
2603            emitter.emitJavascriptList(this, null, TokenID.Semicolon, startLine, false, false);
2604            emitter.recordSourceMappingEnd(this);
2605        };
2606        ASTList.prototype.typeCheck = function (typeFlow) {
2607            var len = this.members.length;
2608            typeFlow.nestingLevel++;
2609            for (var i = 0; i < len; i++) {
2610                if (this.members[i]) {
2611                    this.members[i] = this.members[i].typeCheck(typeFlow);
2612                }
2613            }
2614            typeFlow.nestingLevel--;
2615            return this;
2616        };
2617        return ASTList;
2618    }(AST));
2619    TypeScript.ASTList = ASTList;
2620    var Identifier = /** @class */ (function (_super) {
2621        __extends(Identifier, _super);
2622        // 'actualText' is the text that the user has entered for the identifier. the text might
2623        // include any Unicode escape sequences (e.g.: \u0041 for 'A'). 'text', however, contains
2624        // the resolved value of any escape sequences in the actual text; so in the previous
2625        // example, actualText = '\u0041', text = 'A'.
2626        //
2627        // For purposes of finding a symbol, use text, as this will allow you to match all
2628        // variations of the variable text. For full-fidelity translation of the user input, such
2629        // as emitting, use the actualText field.
2630        //
2631        // Note:
2632        //    To change text, and to avoid running into a situation where 'actualText' does not
2633        //    match 'text', always use setText.
2634        function Identifier(actualText, hasEscapeSequence) {
2635            var _this = _super.call(this, NodeType.Name) || this;
2636            _this.actualText = actualText;
2637            _this.hasEscapeSequence = hasEscapeSequence;
2638            _this.sym = null;
2639            _this.cloId = -1;
2640            _this.setText(actualText, hasEscapeSequence);
2641            return _this;
2642        }
2643        Identifier.prototype.setText = function (actualText, hasEscapeSequence) {
2644            this.actualText = actualText;
2645            if (hasEscapeSequence) {
2646                this.text = AST.getResolvedIdentifierName(actualText);
2647            }
2648            else {
2649                this.text = actualText;
2650            }
2651        };
2652        Identifier.prototype.isMissing = function () { return false; };
2653        Identifier.prototype.isLeaf = function () { return true; };
2654        Identifier.prototype.treeViewLabel = function () {
2655            return "id: " + this.actualText;
2656        };
2657        Identifier.prototype.printLabel = function () {
2658            if (this.actualText) {
2659                return "id: " + this.actualText;
2660            }
2661            else {
2662                return "name node";
2663            }
2664        };
2665        Identifier.prototype.typeCheck = function (typeFlow) {
2666            return typeFlow.typeCheckName(this);
2667        };
2668        Identifier.prototype.emit = function (emitter, tokenId, startLine) {
2669            emitter.emitJavascriptName(this, true);
2670        };
2671        Identifier.fromToken = function (token) {
2672            return new Identifier(token.getText(), token.hasEscapeSequence);
2673        };
2674        return Identifier;
2675    }(AST));
2676    TypeScript.Identifier = Identifier;
2677    var MissingIdentifier = /** @class */ (function (_super) {
2678        __extends(MissingIdentifier, _super);
2679        function MissingIdentifier() {
2680            return _super.call(this, "__missing") || this;
2681        }
2682        MissingIdentifier.prototype.isMissing = function () {
2683            return true;
2684        };
2685        MissingIdentifier.prototype.emit = function (emitter, tokenId, startLine) {
2686            // Emit nothing for a missing ID
2687        };
2688        return MissingIdentifier;
2689    }(Identifier));
2690    TypeScript.MissingIdentifier = MissingIdentifier;
2691    var Label = /** @class */ (function (_super) {
2692        __extends(Label, _super);
2693        function Label(id) {
2694            var _this = _super.call(this, NodeType.Label) || this;
2695            _this.id = id;
2696            return _this;
2697        }
2698        Label.prototype.printLabel = function () { return this.id.actualText + ":"; };
2699        Label.prototype.typeCheck = function (typeFlow) {
2700            this.type = typeFlow.voidType;
2701            return this;
2702        };
2703        Label.prototype.emit = function (emitter, tokenId, startLine) {
2704            emitter.emitParensAndCommentsInPlace(this, true);
2705            emitter.recordSourceMappingStart(this);
2706            emitter.recordSourceMappingStart(this.id);
2707            emitter.writeToOutput(this.id.actualText);
2708            emitter.recordSourceMappingEnd(this.id);
2709            emitter.writeLineToOutput(":");
2710            emitter.recordSourceMappingEnd(this);
2711            emitter.emitParensAndCommentsInPlace(this, false);
2712        };
2713        return Label;
2714    }(AST));
2715    TypeScript.Label = Label;
2716    var Expression = /** @class */ (function (_super) {
2717        __extends(Expression, _super);
2718        function Expression(nodeType) {
2719            return _super.call(this, nodeType) || this;
2720        }
2721        Expression.prototype.isExpression = function () { return true; };
2722        Expression.prototype.isStatementOrExpression = function () { return true; };
2723        return Expression;
2724    }(AST));
2725    TypeScript.Expression = Expression;
2726    var UnaryExpression = /** @class */ (function (_super) {
2727        __extends(UnaryExpression, _super);
2728        function UnaryExpression(nodeType, operand) {
2729            var _this = _super.call(this, nodeType) || this;
2730            _this.operand = operand;
2731            _this.targetType = null; // Target type for an object literal (null if no target type)
2732            _this.castTerm = null;
2733            return _this;
2734        }
2735        UnaryExpression.prototype.addToControlFlow = function (context) {
2736            _super.prototype.addToControlFlow.call(this, context);
2737            // TODO: add successor as catch block/finally block if present
2738            if (this.nodeType == NodeType.Throw) {
2739                context.returnStmt();
2740            }
2741        };
2742        UnaryExpression.prototype.typeCheck = function (typeFlow) {
2743            switch (this.nodeType) {
2744                case NodeType.Not:
2745                    return typeFlow.typeCheckBitNot(this);
2746                case NodeType.LogNot:
2747                    return typeFlow.typeCheckLogNot(this);
2748                case NodeType.Pos:
2749                case NodeType.Neg:
2750                    return typeFlow.typeCheckUnaryNumberOperator(this);
2751                case NodeType.IncPost:
2752                case NodeType.IncPre:
2753                case NodeType.DecPost:
2754                case NodeType.DecPre:
2755                    return typeFlow.typeCheckIncOrDec(this);
2756                case NodeType.ArrayLit:
2757                    typeFlow.typeCheckArrayLit(this);
2758                    return this;
2759                case NodeType.ObjectLit:
2760                    typeFlow.typeCheckObjectLit(this);
2761                    return this;
2762                case NodeType.Throw:
2763                    this.operand = typeFlow.typeCheck(this.operand);
2764                    this.type = typeFlow.voidType;
2765                    return this;
2766                case NodeType.Typeof:
2767                    this.operand = typeFlow.typeCheck(this.operand);
2768                    this.type = typeFlow.stringType;
2769                    return this;
2770                case NodeType.Delete:
2771                    this.operand = typeFlow.typeCheck(this.operand);
2772                    this.type = typeFlow.booleanType;
2773                    break;
2774                case NodeType.TypeAssertion:
2775                    this.castTerm = typeFlow.typeCheck(this.castTerm);
2776                    var applyTargetType = !this.operand.isParenthesized;
2777                    var targetType = applyTargetType ? this.castTerm.type : null;
2778                    typeFlow.checker.typeCheckWithContextualType(targetType, typeFlow.checker.inProvisionalTypecheckMode(), true, this.operand);
2779                    typeFlow.castWithCoercion(this.operand, this.castTerm.type, false, true);
2780                    this.type = this.castTerm.type;
2781                    return this;
2782                case NodeType.Void:
2783                    // REVIEW - Although this is good to do for completeness's sake,
2784                    // this shouldn't be strictly necessary from the void operator's
2785                    // point of view
2786                    this.operand = typeFlow.typeCheck(this.operand);
2787                    this.type = typeFlow.checker.undefinedType;
2788                    break;
2789                default:
2790                    throw new Error("please implement in derived class");
2791            }
2792            return this;
2793        };
2794        UnaryExpression.prototype.emit = function (emitter, tokenId, startLine) {
2795            emitter.emitParensAndCommentsInPlace(this, true);
2796            emitter.recordSourceMappingStart(this);
2797            switch (this.nodeType) {
2798                case NodeType.IncPost:
2799                    emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);
2800                    emitter.writeToOutput("++");
2801                    break;
2802                case NodeType.LogNot:
2803                    emitter.writeToOutput("!");
2804                    emitter.emitJavascript(this.operand, TokenID.Exclamation, false);
2805                    break;
2806                case NodeType.DecPost:
2807                    emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);
2808                    emitter.writeToOutput("--");
2809                    break;
2810                case NodeType.ObjectLit:
2811                    emitter.emitObjectLiteral(this.operand);
2812                    break;
2813                case NodeType.ArrayLit:
2814                    emitter.emitArrayLiteral(this.operand);
2815                    break;
2816                case NodeType.Not:
2817                    emitter.writeToOutput("~");
2818                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
2819                    break;
2820                case NodeType.Neg:
2821                    emitter.writeToOutput("-");
2822                    if (this.operand.nodeType == NodeType.Neg) {
2823                        this.operand.isParenthesized = true;
2824                    }
2825                    emitter.emitJavascript(this.operand, TokenID.Minus, false);
2826                    break;
2827                case NodeType.Pos:
2828                    emitter.writeToOutput("+");
2829                    if (this.operand.nodeType == NodeType.Pos) {
2830                        this.operand.isParenthesized = true;
2831                    }
2832                    emitter.emitJavascript(this.operand, TokenID.Plus, false);
2833                    break;
2834                case NodeType.IncPre:
2835                    emitter.writeToOutput("++");
2836                    emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);
2837                    break;
2838                case NodeType.DecPre:
2839                    emitter.writeToOutput("--");
2840                    emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);
2841                    break;
2842                case NodeType.Throw:
2843                    emitter.writeToOutput("throw ");
2844                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
2845                    emitter.writeToOutput(";");
2846                    break;
2847                case NodeType.Typeof:
2848                    emitter.writeToOutput("typeof ");
2849                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
2850                    break;
2851                case NodeType.Delete:
2852                    emitter.writeToOutput("delete ");
2853                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
2854                    break;
2855                case NodeType.Void:
2856                    emitter.writeToOutput("void ");
2857                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
2858                    break;
2859                case NodeType.TypeAssertion:
2860                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);
2861                    break;
2862                default:
2863                    throw new Error("please implement in derived class");
2864            }
2865            emitter.recordSourceMappingEnd(this);
2866            emitter.emitParensAndCommentsInPlace(this, false);
2867        };
2868        return UnaryExpression;
2869    }(Expression));
2870    TypeScript.UnaryExpression = UnaryExpression;
2871    var CallExpression = /** @class */ (function (_super) {
2872        __extends(CallExpression, _super);
2873        function CallExpression(nodeType, target, arguments) {
2874            var _this = _super.call(this, nodeType) || this;
2875            _this.target = target;
2876            _this.arguments = arguments;
2877            _this.signature = null;
2878            _this.minChar = _this.target.minChar;
2879            return _this;
2880        }
2881        CallExpression.prototype.typeCheck = function (typeFlow) {
2882            if (this.nodeType == NodeType.New) {
2883                return typeFlow.typeCheckNew(this);
2884            }
2885            else {
2886                return typeFlow.typeCheckCall(this);
2887            }
2888        };
2889        CallExpression.prototype.emit = function (emitter, tokenId, startLine) {
2890            emitter.emitParensAndCommentsInPlace(this, true);
2891            emitter.recordSourceMappingStart(this);
2892            if (this.nodeType == NodeType.New) {
2893                emitter.emitNew(this.target, this.arguments);
2894            }
2895            else {
2896                emitter.emitCall(this, this.target, this.arguments);
2897            }
2898            emitter.recordSourceMappingEnd(this);
2899            emitter.emitParensAndCommentsInPlace(this, false);
2900        };
2901        return CallExpression;
2902    }(Expression));
2903    TypeScript.CallExpression = CallExpression;
2904    var BinaryExpression = /** @class */ (function (_super) {
2905        __extends(BinaryExpression, _super);
2906        function BinaryExpression(nodeType, operand1, operand2) {
2907            var _this = _super.call(this, nodeType) || this;
2908            _this.operand1 = operand1;
2909            _this.operand2 = operand2;
2910            return _this;
2911        }
2912        BinaryExpression.prototype.typeCheck = function (typeFlow) {
2913            switch (this.nodeType) {
2914                case NodeType.Dot:
2915                    return typeFlow.typeCheckDotOperator(this);
2916                case NodeType.Asg:
2917                    return typeFlow.typeCheckAsgOperator(this);
2918                case NodeType.Add:
2919                case NodeType.Sub:
2920                case NodeType.Mul:
2921                case NodeType.Div:
2922                case NodeType.Mod:
2923                case NodeType.Or:
2924                case NodeType.And:
2925                    return typeFlow.typeCheckArithmeticOperator(this, false);
2926                case NodeType.Xor:
2927                    return typeFlow.typeCheckBitwiseOperator(this, false);
2928                case NodeType.Ne:
2929                case NodeType.Eq:
2930                    var text;
2931                    if (typeFlow.checker.styleSettings.eqeqeq) {
2932                        text = nodeTypeTable[this.nodeType];
2933                        typeFlow.checker.errorReporter.styleError(this, "use of " + text);
2934                    }
2935                    else if (typeFlow.checker.styleSettings.eqnull) {
2936                        text = nodeTypeTable[this.nodeType];
2937                        if ((this.operand2 !== null) && (this.operand2.nodeType == NodeType.Null)) {
2938                            typeFlow.checker.errorReporter.styleError(this, "use of " + text + " to compare with null");
2939                        }
2940                    }
2941                case NodeType.Eqv:
2942                case NodeType.NEqv:
2943                case NodeType.Lt:
2944                case NodeType.Le:
2945                case NodeType.Ge:
2946                case NodeType.Gt:
2947                    return typeFlow.typeCheckBooleanOperator(this);
2948                case NodeType.Index:
2949                    return typeFlow.typeCheckIndex(this);
2950                case NodeType.Member:
2951                    this.type = typeFlow.voidType;
2952                    return this;
2953                case NodeType.LogOr:
2954                    return typeFlow.typeCheckLogOr(this);
2955                case NodeType.LogAnd:
2956                    return typeFlow.typeCheckLogAnd(this);
2957                case NodeType.AsgAdd:
2958                case NodeType.AsgSub:
2959                case NodeType.AsgMul:
2960                case NodeType.AsgDiv:
2961                case NodeType.AsgMod:
2962                case NodeType.AsgOr:
2963                case NodeType.AsgAnd:
2964                    return typeFlow.typeCheckArithmeticOperator(this, true);
2965                case NodeType.AsgXor:
2966                    return typeFlow.typeCheckBitwiseOperator(this, true);
2967                case NodeType.Lsh:
2968                case NodeType.Rsh:
2969                case NodeType.Rs2:
2970                    return typeFlow.typeCheckShift(this, false);
2971                case NodeType.AsgLsh:
2972                case NodeType.AsgRsh:
2973                case NodeType.AsgRs2:
2974                    return typeFlow.typeCheckShift(this, true);
2975                case NodeType.Comma:
2976                    return typeFlow.typeCheckCommaOperator(this);
2977                case NodeType.InstOf:
2978                    return typeFlow.typeCheckInstOf(this);
2979                case NodeType.In:
2980                    return typeFlow.typeCheckInOperator(this);
2981                case NodeType.From:
2982                    typeFlow.checker.errorReporter.simpleError(this, "Illegal use of 'from' keyword in binary expression");
2983                    break;
2984                default:
2985                    throw new Error("please implement in derived class");
2986            }
2987            return this;
2988        };
2989        BinaryExpression.prototype.emit = function (emitter, tokenId, startLine) {
2990            var binTokenId = nodeTypeToTokTable[this.nodeType];
2991            emitter.emitParensAndCommentsInPlace(this, true);
2992            emitter.recordSourceMappingStart(this);
2993            if (binTokenId != undefined) {
2994                emitter.emitJavascript(this.operand1, binTokenId, false);
2995                if (tokenTable[binTokenId].text == "instanceof") {
2996                    emitter.writeToOutput(" instanceof ");
2997                }
2998                else if (tokenTable[binTokenId].text == "in") {
2999                    emitter.writeToOutput(" in ");
3000                }
3001                else {
3002                    emitter.writeToOutputTrimmable(" " + tokenTable[binTokenId].text + " ");
3003                }
3004                emitter.emitJavascript(this.operand2, binTokenId, false);
3005            }
3006            else {
3007                switch (this.nodeType) {
3008                    case NodeType.Dot:
3009                        if (!emitter.tryEmitConstant(this)) {
3010                            emitter.emitJavascript(this.operand1, TokenID.Dot, false);
3011                            emitter.writeToOutput(".");
3012                            emitter.emitJavascriptName(this.operand2, false);
3013                        }
3014                        break;
3015                    case NodeType.Index:
3016                        emitter.emitIndex(this.operand1, this.operand2);
3017                        break;
3018                    case NodeType.Member:
3019                        if (this.operand2.nodeType == NodeType.FuncDecl && this.operand2.isAccessor()) {
3020                            var funcDecl = this.operand2;
3021                            if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {
3022                                emitter.writeToOutput("get ");
3023                            }
3024                            else {
3025                                emitter.writeToOutput("set ");
3026                            }
3027                            emitter.emitJavascript(this.operand1, TokenID.Colon, false);
3028                        }
3029                        else {
3030                            emitter.emitJavascript(this.operand1, TokenID.Colon, false);
3031                            emitter.writeToOutputTrimmable(": ");
3032                        }
3033                        emitter.emitJavascript(this.operand2, TokenID.Comma, false);
3034                        break;
3035                    case NodeType.Comma:
3036                        emitter.emitJavascript(this.operand1, TokenID.Comma, false);
3037                        if (emitter.emitState.inObjectLiteral) {
3038                            emitter.writeLineToOutput(", ");
3039                        }
3040                        else {
3041                            emitter.writeToOutput(",");
3042                        }
3043                        emitter.emitJavascript(this.operand2, TokenID.Comma, false);
3044                        break;
3045                    case NodeType.Is:
3046                        throw new Error("should be de-sugared during type check");
3047                    default:
3048                        throw new Error("please implement in derived class");
3049                }
3050            }
3051            emitter.recordSourceMappingEnd(this);
3052            emitter.emitParensAndCommentsInPlace(this, false);
3053        };
3054        return BinaryExpression;
3055    }(Expression));
3056    TypeScript.BinaryExpression = BinaryExpression;
3057    var ConditionalExpression = /** @class */ (function (_super) {
3058        __extends(ConditionalExpression, _super);
3059        function ConditionalExpression(operand1, operand2, operand3) {
3060            var _this = _super.call(this, NodeType.ConditionalExpression) || this;
3061            _this.operand1 = operand1;
3062            _this.operand2 = operand2;
3063            _this.operand3 = operand3;
3064            return _this;
3065        }
3066        ConditionalExpression.prototype.typeCheck = function (typeFlow) {
3067            return typeFlow.typeCheckQMark(this);
3068        };
3069        ConditionalExpression.prototype.emit = function (emitter, tokenId, startLine) {
3070            emitter.emitParensAndCommentsInPlace(this, true);
3071            emitter.recordSourceMappingStart(this);
3072            emitter.emitJavascript(this.operand1, TokenID.Question, false);
3073            emitter.writeToOutput(" ? ");
3074            emitter.emitJavascript(this.operand2, TokenID.Question, false);
3075            emitter.writeToOutput(" : ");
3076            emitter.emitJavascript(this.operand3, TokenID.Question, false);
3077            emitter.recordSourceMappingEnd(this);
3078            emitter.emitParensAndCommentsInPlace(this, false);
3079        };
3080        return ConditionalExpression;
3081    }(Expression));
3082    TypeScript.ConditionalExpression = ConditionalExpression;
3083    var NumberLiteral = /** @class */ (function (_super) {
3084        __extends(NumberLiteral, _super);
3085        function NumberLiteral(value, hasEmptyFraction) {
3086            var _this = _super.call(this, NodeType.NumberLit) || this;
3087            _this.value = value;
3088            _this.hasEmptyFraction = hasEmptyFraction;
3089            _this.isNegativeZero = false;
3090            return _this;
3091        }
3092        NumberLiteral.prototype.typeCheck = function (typeFlow) {
3093            this.type = typeFlow.doubleType;
3094            return this;
3095        };
3096        NumberLiteral.prototype.treeViewLabel = function () {
3097            return "num: " + this.printLabel();
3098        };
3099        NumberLiteral.prototype.emit = function (emitter, tokenId, startLine) {
3100            emitter.emitParensAndCommentsInPlace(this, true);
3101            emitter.recordSourceMappingStart(this);
3102            if (this.isNegativeZero) {
3103                emitter.writeToOutput("-");
3104            }
3105            emitter.writeToOutput(this.value.toString());
3106            if (this.hasEmptyFraction)
3107                emitter.writeToOutput(".0");
3108            emitter.recordSourceMappingEnd(this);
3109            emitter.emitParensAndCommentsInPlace(this, false);
3110        };
3111        NumberLiteral.prototype.printLabel = function () {
3112            if (Math.floor(this.value) != this.value) {
3113                return this.value.toFixed(2).toString();
3114            }
3115            else if (this.hasEmptyFraction) {
3116                return this.value.toString() + ".0";
3117            }
3118            else {
3119                return this.value.toString();
3120            }
3121        };
3122        return NumberLiteral;
3123    }(Expression));
3124    TypeScript.NumberLiteral = NumberLiteral;
3125    var RegexLiteral = /** @class */ (function (_super) {
3126        __extends(RegexLiteral, _super);
3127        function RegexLiteral(regex) {
3128            var _this = _super.call(this, NodeType.Regex) || this;
3129            _this.regex = regex;
3130            return _this;
3131        }
3132        RegexLiteral.prototype.typeCheck = function (typeFlow) {
3133            this.type = typeFlow.regexType;
3134            return this;
3135        };
3136        RegexLiteral.prototype.emit = function (emitter, tokenId, startLine) {
3137            emitter.emitParensAndCommentsInPlace(this, true);
3138            emitter.recordSourceMappingStart(this);
3139            emitter.writeToOutput(this.regex.toString());
3140            emitter.recordSourceMappingEnd(this);
3141            emitter.emitParensAndCommentsInPlace(this, false);
3142        };
3143        return RegexLiteral;
3144    }(Expression));
3145    TypeScript.RegexLiteral = RegexLiteral;
3146    var StringLiteral = /** @class */ (function (_super) {
3147        __extends(StringLiteral, _super);
3148        function StringLiteral(text) {
3149            var _this = _super.call(this, NodeType.QString) || this;
3150            _this.text = text;
3151            return _this;
3152        }
3153        StringLiteral.prototype.emit = function (emitter, tokenId, startLine) {
3154            emitter.emitParensAndCommentsInPlace(this, true);
3155            emitter.recordSourceMappingStart(this);
3156            emitter.emitStringLiteral(this.text);
3157            emitter.recordSourceMappingEnd(this);
3158            emitter.emitParensAndCommentsInPlace(this, false);
3159        };
3160        StringLiteral.prototype.typeCheck = function (typeFlow) {
3161            this.type = typeFlow.stringType;
3162            return this;
3163        };
3164        StringLiteral.prototype.treeViewLabel = function () {
3165            return "st: " + this.text;
3166        };
3167        StringLiteral.prototype.printLabel = function () {
3168            return this.text;
3169        };
3170        return StringLiteral;
3171    }(Expression));
3172    TypeScript.StringLiteral = StringLiteral;
3173    var ModuleElement = /** @class */ (function (_super) {
3174        __extends(ModuleElement, _super);
3175        function ModuleElement(nodeType) {
3176            return _super.call(this, nodeType) || this;
3177        }
3178        return ModuleElement;
3179    }(AST));
3180    TypeScript.ModuleElement = ModuleElement;
3181    var ImportDeclaration = /** @class */ (function (_super) {
3182        __extends(ImportDeclaration, _super);
3183        function ImportDeclaration(id, alias) {
3184            var _this = _super.call(this, NodeType.ImportDeclaration) || this;
3185            _this.id = id;
3186            _this.alias = alias;
3187            _this.varFlags = VarFlags.None;
3188            _this.isDynamicImport = false;
3189            return _this;
3190        }
3191        ImportDeclaration.prototype.isStatementOrExpression = function () { return true; };
3192        ImportDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
3193            var mod = this.alias.type;
3194            // REVIEW: Only modules may be aliased for now, though there's no real
3195            // restriction on what the type symbol may be
3196            if (!this.isDynamicImport || (this.id.sym && !this.id.sym.onlyReferencedAsTypeRef)) {
3197                var prevModAliasId = emitter.modAliasId;
3198                var prevFirstModAlias = emitter.firstModAlias;
3199                emitter.recordSourceMappingStart(this);
3200                emitter.emitParensAndCommentsInPlace(this, true);
3201                emitter.writeToOutput("var " + this.id.actualText + " = ");
3202                emitter.modAliasId = this.id.actualText;
3203                emitter.firstModAlias = this.firstAliasedModToString();
3204                emitter.emitJavascript(this.alias, TokenID.Tilde, false);
3205                // the dynamic import case will insert the semi-colon automatically
3206                if (!this.isDynamicImport) {
3207                    emitter.writeToOutput(";");
3208                }
3209                emitter.emitParensAndCommentsInPlace(this, false);
3210                emitter.recordSourceMappingEnd(this);
3211                emitter.modAliasId = prevModAliasId;
3212                emitter.firstModAlias = prevFirstModAlias;
3213            }
3214        };
3215        ImportDeclaration.prototype.typeCheck = function (typeFlow) {
3216            return typeFlow.typeCheckImportDecl(this);
3217        };
3218        ImportDeclaration.prototype.getAliasName = function (aliasAST) {
3219            if (aliasAST === void 0) { aliasAST = this.alias; }
3220            if (aliasAST.nodeType == NodeType.Name) {
3221                return aliasAST.actualText;
3222            }
3223            else {
3224                var dotExpr = aliasAST;
3225                return this.getAliasName(dotExpr.operand1) + "." + this.getAliasName(dotExpr.operand2);
3226            }
3227        };
3228        ImportDeclaration.prototype.firstAliasedModToString = function () {
3229            if (this.alias.nodeType == NodeType.Name) {
3230                return this.alias.actualText;
3231            }
3232            else {
3233                var dotExpr = this.alias;
3234                var firstMod = dotExpr.operand1;
3235                return firstMod.actualText;
3236            }
3237        };
3238        return ImportDeclaration;
3239    }(ModuleElement));
3240    TypeScript.ImportDeclaration = ImportDeclaration;
3241    var BoundDecl = /** @class */ (function (_super) {
3242        __extends(BoundDecl, _super);
3243        function BoundDecl(id, nodeType, nestingLevel) {
3244            var _this = _super.call(this, nodeType) || this;
3245            _this.id = id;
3246            _this.nestingLevel = nestingLevel;
3247            _this.init = null;
3248            _this.typeExpr = null;
3249            _this.varFlags = VarFlags.None;
3250            _this.sym = null;
3251            return _this;
3252        }
3253        BoundDecl.prototype.isStatementOrExpression = function () { return true; };
3254        BoundDecl.prototype.isPrivate = function () { return hasFlag(this.varFlags, VarFlags.Private); };
3255        BoundDecl.prototype.isPublic = function () { return hasFlag(this.varFlags, VarFlags.Public); };
3256        BoundDecl.prototype.isProperty = function () { return hasFlag(this.varFlags, VarFlags.Property); };
3257        BoundDecl.prototype.typeCheck = function (typeFlow) {
3258            return typeFlow.typeCheckBoundDecl(this);
3259        };
3260        BoundDecl.prototype.printLabel = function () {
3261            return this.treeViewLabel();
3262        };
3263        return BoundDecl;
3264    }(AST));
3265    TypeScript.BoundDecl = BoundDecl;
3266    var VarDecl = /** @class */ (function (_super) {
3267        __extends(VarDecl, _super);
3268        function VarDecl(id, nest) {
3269            return _super.call(this, id, NodeType.VarDecl, nest) || this;
3270        }
3271        VarDecl.prototype.isAmbient = function () { return hasFlag(this.varFlags, VarFlags.Ambient); };
3272        VarDecl.prototype.isExported = function () { return hasFlag(this.varFlags, VarFlags.Exported); };
3273        VarDecl.prototype.isStatic = function () { return hasFlag(this.varFlags, VarFlags.Static); };
3274        VarDecl.prototype.emit = function (emitter, tokenId, startLine) {
3275            emitter.emitJavascriptVarDecl(this, tokenId);
3276        };
3277        VarDecl.prototype.treeViewLabel = function () {
3278            return "var " + this.id.actualText;
3279        };
3280        return VarDecl;
3281    }(BoundDecl));
3282    TypeScript.VarDecl = VarDecl;
3283    var ArgDecl = /** @class */ (function (_super) {
3284        __extends(ArgDecl, _super);
3285        function ArgDecl(id) {
3286            var _this = _super.call(this, id, NodeType.ArgDecl, 0) || this;
3287            _this.isOptional = false;
3288            _this.parameterPropertySym = null;
3289            return _this;
3290        }
3291        ArgDecl.prototype.isOptionalArg = function () { return this.isOptional || this.init; };
3292        ArgDecl.prototype.treeViewLabel = function () {
3293            return "arg: " + this.id.actualText;
3294        };
3295        ArgDecl.prototype.emit = function (emitter, tokenId, startLine) {
3296            emitter.emitParensAndCommentsInPlace(this, true);
3297            emitter.recordSourceMappingStart(this);
3298            emitter.writeToOutput(this.id.actualText);
3299            emitter.recordSourceMappingEnd(this);
3300            emitter.emitParensAndCommentsInPlace(this, false);
3301        };
3302        return ArgDecl;
3303    }(BoundDecl));
3304    TypeScript.ArgDecl = ArgDecl;
3305    var internalId = 0;
3306    var FuncDecl = /** @class */ (function (_super) {
3307        __extends(FuncDecl, _super);
3308        function FuncDecl(name, bod, isConstructor, arguments, vars, scopes, statics, nodeType) {
3309            var _this = _super.call(this, nodeType) || this;
3310            _this.name = name;
3311            _this.bod = bod;
3312            _this.isConstructor = isConstructor;
3313            _this.arguments = arguments;
3314            _this.vars = vars;
3315            _this.scopes = scopes;
3316            _this.statics = statics;
3317            _this.hint = null;
3318            _this.fncFlags = FncFlags.None;
3319            _this.returnTypeAnnotation = null;
3320            _this.variableArgList = false;
3321            _this.jumpRefs = null;
3322            _this.internalNameCache = null;
3323            _this.tmp1Declared = false;
3324            _this.enclosingFnc = null;
3325            _this.freeVariables = [];
3326            _this.unitIndex = -1;
3327            _this.classDecl = null;
3328            _this.boundToProperty = null;
3329            _this.isOverload = false;
3330            _this.innerStaticFuncs = [];
3331            _this.isTargetTypedAsMethod = false;
3332            _this.isInlineCallLiteral = false;
3333            _this.accessorSymbol = null;
3334            _this.leftCurlyCount = 0;
3335            _this.rightCurlyCount = 0;
3336            _this.returnStatementsWithExpressions = [];
3337            _this.scopeType = null; // Type of the FuncDecl, before target typing
3338            _this.endingToken = null;
3339            return _this;
3340        }
3341        FuncDecl.prototype.internalName = function () {
3342            if (this.internalNameCache == null) {
3343                var extName = this.getNameText();
3344                if (extName) {
3345                    this.internalNameCache = "_internal_" + extName;
3346                }
3347                else {
3348                    this.internalNameCache = "_internal_" + internalId++;
3349                }
3350            }
3351            return this.internalNameCache;
3352        };
3353        FuncDecl.prototype.hasSelfReference = function () { return hasFlag(this.fncFlags, FncFlags.HasSelfReference); };
3354        FuncDecl.prototype.setHasSelfReference = function () { this.fncFlags |= FncFlags.HasSelfReference; };
3355        FuncDecl.prototype.addCloRef = function (id, sym) {
3356            if (this.envids == null) {
3357                this.envids = new Identifier[];
3358            }
3359            this.envids[this.envids.length] = id;
3360            var outerFnc = this.enclosingFnc;
3361            if (sym) {
3362                while (outerFnc && (outerFnc.type.symbol != sym.container)) {
3363                    outerFnc.addJumpRef(sym);
3364                    outerFnc = outerFnc.enclosingFnc;
3365                }
3366            }
3367            return this.envids.length - 1;
3368        };
3369        FuncDecl.prototype.addJumpRef = function (sym) {
3370            if (this.jumpRefs == null) {
3371                this.jumpRefs = new Identifier[];
3372            }
3373            var id = new Identifier(sym.name);
3374            this.jumpRefs[this.jumpRefs.length] = id;
3375            id.sym = sym;
3376            id.cloId = this.addCloRef(id, null);
3377        };
3378        FuncDecl.prototype.buildControlFlow = function () {
3379            var entry = new BasicBlock();
3380            var exit = new BasicBlock();
3381            var context = new ControlFlowContext(entry, exit);
3382            var controlFlowPrefix = function (ast, parent, walker) {
3383                ast.addToControlFlow(walker.state);
3384                return ast;
3385            };
3386            var walker = getAstWalkerFactory().getWalker(controlFlowPrefix, null, null, context);
3387            context.walker = walker;
3388            walker.walk(this.bod, this);
3389            return context;
3390        };
3391        FuncDecl.prototype.typeCheck = function (typeFlow) {
3392            return typeFlow.typeCheckFunction(this);
3393        };
3394        FuncDecl.prototype.emit = function (emitter, tokenId, startLine) {
3395            emitter.emitJavascriptFunction(this);
3396        };
3397        FuncDecl.prototype.getNameText = function () {
3398            if (this.name) {
3399                return this.name.actualText;
3400            }
3401            else {
3402                return this.hint;
3403            }
3404        };
3405        FuncDecl.prototype.isMethod = function () {
3406            return (this.fncFlags & FncFlags.Method) != FncFlags.None;
3407        };
3408        FuncDecl.prototype.isCallMember = function () { return hasFlag(this.fncFlags, FncFlags.CallMember); };
3409        FuncDecl.prototype.isConstructMember = function () { return hasFlag(this.fncFlags, FncFlags.ConstructMember); };
3410        FuncDecl.prototype.isIndexerMember = function () { return hasFlag(this.fncFlags, FncFlags.IndexerMember); };
3411        FuncDecl.prototype.isSpecialFn = function () { return this.isCallMember() || this.isIndexerMember() || this.isConstructMember(); };
3412        FuncDecl.prototype.isAnonymousFn = function () { return this.name === null; };
3413        FuncDecl.prototype.isAccessor = function () { return hasFlag(this.fncFlags, FncFlags.GetAccessor) || hasFlag(this.fncFlags, FncFlags.SetAccessor); };
3414        FuncDecl.prototype.isGetAccessor = function () { return hasFlag(this.fncFlags, FncFlags.GetAccessor); };
3415        FuncDecl.prototype.isSetAccessor = function () { return hasFlag(this.fncFlags, FncFlags.SetAccessor); };
3416        FuncDecl.prototype.isAmbient = function () { return hasFlag(this.fncFlags, FncFlags.Ambient); };
3417        FuncDecl.prototype.isExported = function () { return hasFlag(this.fncFlags, FncFlags.Exported); };
3418        FuncDecl.prototype.isPrivate = function () { return hasFlag(this.fncFlags, FncFlags.Private); };
3419        FuncDecl.prototype.isPublic = function () { return hasFlag(this.fncFlags, FncFlags.Public); };
3420        FuncDecl.prototype.isStatic = function () { return hasFlag(this.fncFlags, FncFlags.Static); };
3421        FuncDecl.prototype.treeViewLabel = function () {
3422            if (this.name == null) {
3423                return "funcExpr";
3424            }
3425            else {
3426                return "func: " + this.name.actualText;
3427            }
3428        };
3429        FuncDecl.prototype.ClearFlags = function () {
3430            this.fncFlags = FncFlags.None;
3431        };
3432        FuncDecl.prototype.isSignature = function () { return (this.fncFlags & FncFlags.Signature) != FncFlags.None; };
3433        FuncDecl.prototype.hasStaticDeclarations = function () { return (!this.isConstructor && (this.statics.members.length > 0 || this.innerStaticFuncs.length > 0)); };
3434        return FuncDecl;
3435    }(AST));
3436    TypeScript.FuncDecl = FuncDecl;
3437    var LocationInfo = /** @class */ (function () {
3438        function LocationInfo(filename, lineMap, unitIndex) {
3439            this.filename = filename;
3440            this.lineMap = lineMap;
3441            this.unitIndex = unitIndex;
3442        }
3443        return LocationInfo;
3444    }());
3445    TypeScript.LocationInfo = LocationInfo;
3446    TypeScript.unknownLocationInfo = new LocationInfo("unknown", null, -1);
3447    var Script = /** @class */ (function (_super) {
3448        __extends(Script, _super);
3449        function Script(vars, scopes) {
3450            var _this = _super.call(this, new Identifier("script"), null, false, null, vars, scopes, null, NodeType.Script) || this;
3451            _this.locationInfo = null;
3452            _this.referencedFiles = [];
3453            _this.requiresGlobal = false;
3454            _this.requiresInherits = false;
3455            _this.isResident = false;
3456            _this.isDeclareFile = false;
3457            _this.hasBeenTypeChecked = false;
3458            _this.topLevelMod = null;
3459            _this.leftCurlyCount = 0;
3460            _this.rightCurlyCount = 0;
3461            // Remember if the script contains Unicode chars, that is needed when generating code for this script object to decide the output file correct encoding.
3462            _this.containsUnicodeChar = false;
3463            _this.containsUnicodeCharInComment = false;
3464            _this.vars = vars;
3465            _this.scopes = scopes;
3466            return _this;
3467        }
3468        Script.prototype.typeCheck = function (typeFlow) {
3469            return typeFlow.typeCheckScript(this);
3470        };
3471        Script.prototype.treeViewLabel = function () {
3472            return "Script";
3473        };
3474        Script.prototype.emitRequired = function () {
3475            if (!this.isDeclareFile && !this.isResident && this.bod) {
3476                for (var i = 0, len = this.bod.members.length; i < len; i++) {
3477                    var stmt = this.bod.members[i];
3478                    if (stmt.nodeType == NodeType.ModuleDeclaration) {
3479                        if (!hasFlag(stmt.modFlags, ModuleFlags.ShouldEmitModuleDecl | ModuleFlags.Ambient)) {
3480                            return true;
3481                        }
3482                    }
3483                    else if (stmt.nodeType == NodeType.ClassDeclaration) {
3484                        if (!hasFlag(stmt.varFlags, VarFlags.Ambient)) {
3485                            return true;
3486                        }
3487                    }
3488                    else if (stmt.nodeType == NodeType.VarDecl) {
3489                        if (!hasFlag(stmt.varFlags, VarFlags.Ambient)) {
3490                            return true;
3491                        }
3492                    }
3493                    else if (stmt.nodeType == NodeType.FuncDecl) {
3494                        if (!stmt.isSignature()) {
3495                            return true;
3496                        }
3497                    }
3498                    else if (stmt.nodeType != NodeType.InterfaceDeclaration && stmt.nodeType != NodeType.Empty) {
3499                        return true;
3500                    }
3501                }
3502            }
3503            return false;
3504        };
3505        Script.prototype.emit = function (emitter, tokenId, startLine) {
3506            if (this.emitRequired()) {
3507                emitter.emitParensAndCommentsInPlace(this, true);
3508                emitter.recordSourceMappingStart(this);
3509                emitter.emitJavascriptList(this.bod, null, TokenID.Semicolon, true, false, false, true, this.requiresInherits);
3510                emitter.recordSourceMappingEnd(this);
3511                emitter.emitParensAndCommentsInPlace(this, false);
3512            }
3513        };
3514        return Script;
3515    }(FuncDecl));
3516    TypeScript.Script = Script;
3517    var NamedDeclaration = /** @class */ (function (_super) {
3518        __extends(NamedDeclaration, _super);
3519        function NamedDeclaration(nodeType, name, members) {
3520            var _this = _super.call(this, nodeType) || this;
3521            _this.name = name;
3522            _this.members = members;
3523            _this.leftCurlyCount = 0;
3524            _this.rightCurlyCount = 0;
3525            return _this;
3526        }
3527        return NamedDeclaration;
3528    }(ModuleElement));
3529    TypeScript.NamedDeclaration = NamedDeclaration;
3530    var ModuleDeclaration = /** @class */ (function (_super) {
3531        __extends(ModuleDeclaration, _super);
3532        function ModuleDeclaration(name, members, vars, scopes, endingToken) {
3533            var _this = _super.call(this, NodeType.ModuleDeclaration, name, members) || this;
3534            _this.endingToken = endingToken;
3535            _this.modFlags = ModuleFlags.ShouldEmitModuleDecl;
3536            _this.amdDependencies = [];
3537            // Remember if the module contains Unicode chars, that is needed for dynamic module as we will generate a file for each.
3538            _this.containsUnicodeChar = false;
3539            _this.containsUnicodeCharInComment = false;
3540            _this.vars = vars;
3541            _this.scopes = scopes;
3542            _this.prettyName = _this.name.actualText;
3543            return _this;
3544        }
3545        ModuleDeclaration.prototype.isExported = function () { return hasFlag(this.modFlags, ModuleFlags.Exported); };
3546        ModuleDeclaration.prototype.isAmbient = function () { return hasFlag(this.modFlags, ModuleFlags.Ambient); };
3547        ModuleDeclaration.prototype.isEnum = function () { return hasFlag(this.modFlags, ModuleFlags.IsEnum); };
3548        ModuleDeclaration.prototype.recordNonInterface = function () {
3549            this.modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;
3550        };
3551        ModuleDeclaration.prototype.typeCheck = function (typeFlow) {
3552            return typeFlow.typeCheckModule(this);
3553        };
3554        ModuleDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
3555            if (!hasFlag(this.modFlags, ModuleFlags.ShouldEmitModuleDecl)) {
3556                emitter.emitParensAndCommentsInPlace(this, true);
3557                emitter.recordSourceMappingStart(this);
3558                emitter.emitJavascriptModule(this);
3559                emitter.recordSourceMappingEnd(this);
3560                emitter.emitParensAndCommentsInPlace(this, false);
3561            }
3562        };
3563        return ModuleDeclaration;
3564    }(NamedDeclaration));
3565    TypeScript.ModuleDeclaration = ModuleDeclaration;
3566    var TypeDeclaration = /** @class */ (function (_super) {
3567        __extends(TypeDeclaration, _super);
3568        function TypeDeclaration(nodeType, name, extendsList, implementsList, members) {
3569            var _this = _super.call(this, nodeType, name, members) || this;
3570            _this.extendsList = extendsList;
3571            _this.implementsList = implementsList;
3572            _this.varFlags = VarFlags.None;
3573            return _this;
3574        }
3575        TypeDeclaration.prototype.isExported = function () {
3576            return hasFlag(this.varFlags, VarFlags.Exported);
3577        };
3578        TypeDeclaration.prototype.isAmbient = function () {
3579            return hasFlag(this.varFlags, VarFlags.Ambient);
3580        };
3581        return TypeDeclaration;
3582    }(NamedDeclaration));
3583    TypeScript.TypeDeclaration = TypeDeclaration;
3584    var ClassDeclaration = /** @class */ (function (_super) {
3585        __extends(ClassDeclaration, _super);
3586        function ClassDeclaration(name, members, extendsList, implementsList) {
3587            var _this = _super.call(this, NodeType.ClassDeclaration, name, extendsList, implementsList, members) || this;
3588            _this.knownMemberNames = {};
3589            _this.constructorDecl = null;
3590            _this.constructorNestingLevel = 0;
3591            _this.endingToken = null;
3592            return _this;
3593        }
3594        ClassDeclaration.prototype.typeCheck = function (typeFlow) {
3595            return typeFlow.typeCheckClass(this);
3596        };
3597        ClassDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
3598            emitter.emitJavascriptClass(this);
3599        };
3600        return ClassDeclaration;
3601    }(TypeDeclaration));
3602    TypeScript.ClassDeclaration = ClassDeclaration;
3603    var InterfaceDeclaration = /** @class */ (function (_super) {
3604        __extends(InterfaceDeclaration, _super);
3605        function InterfaceDeclaration(name, members, extendsList, implementsList) {
3606            return _super.call(this, NodeType.InterfaceDeclaration, name, extendsList, implementsList, members) || this;
3607        }
3608        InterfaceDeclaration.prototype.typeCheck = function (typeFlow) {
3609            return typeFlow.typeCheckInterface(this);
3610        };
3611        InterfaceDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
3612        };
3613        return InterfaceDeclaration;
3614    }(TypeDeclaration));
3615    TypeScript.InterfaceDeclaration = InterfaceDeclaration;
3616    var Statement = /** @class */ (function (_super) {
3617        __extends(Statement, _super);
3618        function Statement(nodeType) {
3619            var _this = _super.call(this, nodeType) || this;
3620            _this.flags |= ASTFlags.IsStatement;
3621            return _this;
3622        }
3623        Statement.prototype.isLoop = function () { return false; };
3624        Statement.prototype.isStatementOrExpression = function () { return true; };
3625        Statement.prototype.isCompoundStatement = function () { return this.isLoop(); };
3626        Statement.prototype.typeCheck = function (typeFlow) {
3627            this.type = typeFlow.voidType;
3628            return this;
3629        };
3630        return Statement;
3631    }(ModuleElement));
3632    TypeScript.Statement = Statement;
3633    var LabeledStatement = /** @class */ (function (_super) {
3634        __extends(LabeledStatement, _super);
3635        function LabeledStatement(labels, stmt) {
3636            var _this = _super.call(this, NodeType.LabeledStatement) || this;
3637            _this.labels = labels;
3638            _this.stmt = stmt;
3639            return _this;
3640        }
3641        LabeledStatement.prototype.emit = function (emitter, tokenId, startLine) {
3642            emitter.emitParensAndCommentsInPlace(this, true);
3643            emitter.recordSourceMappingStart(this);
3644            if (this.labels) {
3645                var labelsLen = this.labels.members.length;
3646                for (var i = 0; i < labelsLen; i++) {
3647                    this.labels.members[i].emit(emitter, tokenId, startLine);
3648                }
3649            }
3650            this.stmt.emit(emitter, tokenId, true);
3651            emitter.recordSourceMappingEnd(this);
3652            emitter.emitParensAndCommentsInPlace(this, false);
3653        };
3654        LabeledStatement.prototype.typeCheck = function (typeFlow) {
3655            typeFlow.typeCheck(this.labels);
3656            this.stmt = this.stmt.typeCheck(typeFlow);
3657            return this;
3658        };
3659        LabeledStatement.prototype.addToControlFlow = function (context) {
3660            var beforeBB = context.current;
3661            var bb = new BasicBlock();
3662            context.current = bb;
3663            beforeBB.addSuccessor(bb);
3664        };
3665        return LabeledStatement;
3666    }(Statement));
3667    TypeScript.LabeledStatement = LabeledStatement;
3668    var Block = /** @class */ (function (_super) {
3669        __extends(Block, _super);
3670        function Block(statements, isStatementBlock) {
3671            var _this = _super.call(this, NodeType.Block) || this;
3672            _this.statements = statements;
3673            _this.isStatementBlock = isStatementBlock;
3674            return _this;
3675        }
3676        Block.prototype.emit = function (emitter, tokenId, startLine) {
3677            emitter.emitParensAndCommentsInPlace(this, true);
3678            emitter.recordSourceMappingStart(this);
3679            if (this.isStatementBlock) {
3680                emitter.writeLineToOutput(" {");
3681                emitter.indenter.increaseIndent();
3682            }
3683            else {
3684                emitter.setInVarBlock(this.statements.members.length);
3685            }
3686            var temp = emitter.setInObjectLiteral(false);
3687            if (this.statements) {
3688                emitter.emitJavascriptList(this.statements, null, TokenID.Semicolon, true, false, false);
3689            }
3690            if (this.isStatementBlock) {
3691                emitter.indenter.decreaseIndent();
3692                emitter.emitIndent();
3693                emitter.writeToOutput("}");
3694            }
3695            emitter.setInObjectLiteral(temp);
3696            emitter.recordSourceMappingEnd(this);
3697            emitter.emitParensAndCommentsInPlace(this, false);
3698        };
3699        Block.prototype.addToControlFlow = function (context) {
3700            var afterIfNeeded = new BasicBlock();
3701            context.pushStatement(this, context.current, afterIfNeeded);
3702            if (this.statements) {
3703                context.walk(this.statements, this);
3704            }
3705            context.walker.options.goChildren = false;
3706            context.popStatement();
3707            if (afterIfNeeded.predecessors.length > 0) {
3708                context.current.addSuccessor(afterIfNeeded);
3709                context.current = afterIfNeeded;
3710            }
3711        };
3712        Block.prototype.typeCheck = function (typeFlow) {
3713            if (!typeFlow.checker.styleSettings.emptyBlocks) {
3714                if ((this.statements === null) || (this.statements.members.length == 0)) {
3715                    typeFlow.checker.errorReporter.styleError(this, "empty block");
3716                }
3717            }
3718            typeFlow.typeCheck(this.statements);
3719            return this;
3720        };
3721        return Block;
3722    }(Statement));
3723    TypeScript.Block = Block;
3724    var Jump = /** @class */ (function (_super) {
3725        __extends(Jump, _super);
3726        function Jump(nodeType) {
3727            var _this = _super.call(this, nodeType) || this;
3728            _this.target = null;
3729            _this.resolvedTarget = null;
3730            return _this;
3731        }
3732        Jump.prototype.hasExplicitTarget = function () { return (this.target); };
3733        Jump.prototype.setResolvedTarget = function (parser, stmt) {
3734            if (stmt.isLoop()) {
3735                this.resolvedTarget = stmt;
3736                return true;
3737            }
3738            if (this.nodeType === NodeType.Continue) {
3739                parser.reportParseError("continue statement applies only to loops");
3740                return false;
3741            }
3742            else {
3743                if ((stmt.nodeType == NodeType.Switch) || this.hasExplicitTarget()) {
3744                    this.resolvedTarget = stmt;
3745                    return true;
3746                }
3747                else {
3748                    parser.reportParseError("break statement with no label can apply only to a loop or switch statement");
3749                    return false;
3750                }
3751            }
3752        };
3753        Jump.prototype.addToControlFlow = function (context) {
3754            _super.prototype.addToControlFlow.call(this, context);
3755            context.unconditionalBranch(this.resolvedTarget, (this.nodeType == NodeType.Continue));
3756        };
3757        Jump.prototype.emit = function (emitter, tokenId, startLine) {
3758            emitter.emitParensAndCommentsInPlace(this, true);
3759            emitter.recordSourceMappingStart(this);
3760            if (this.nodeType == NodeType.Break) {
3761                emitter.writeToOutput("break");
3762            }
3763            else {
3764                emitter.writeToOutput("continue");
3765            }
3766            if (this.hasExplicitTarget()) {
3767                emitter.writeToOutput(" " + this.target);
3768            }
3769            emitter.recordSourceMappingEnd(this);
3770            emitter.writeToOutput(";");
3771            emitter.emitParensAndCommentsInPlace(this, false);
3772        };
3773        return Jump;
3774    }(Statement));
3775    TypeScript.Jump = Jump;
3776    var WhileStatement = /** @class */ (function (_super) {
3777        __extends(WhileStatement, _super);
3778        function WhileStatement(cond) {
3779            var _this = _super.call(this, NodeType.While) || this;
3780            _this.cond = cond;
3781            _this.body = null;
3782            return _this;
3783        }
3784        WhileStatement.prototype.isLoop = function () { return true; };
3785        WhileStatement.prototype.emit = function (emitter, tokenId, startLine) {
3786            emitter.emitParensAndCommentsInPlace(this, true);
3787            emitter.recordSourceMappingStart(this);
3788            var temp = emitter.setInObjectLiteral(false);
3789            emitter.writeToOutput("while(");
3790            emitter.emitJavascript(this.cond, TokenID.While, false);
3791            emitter.writeToOutput(")");
3792            emitter.emitJavascriptStatements(this.body, false, false);
3793            emitter.setInObjectLiteral(temp);
3794            emitter.recordSourceMappingEnd(this);
3795            emitter.emitParensAndCommentsInPlace(this, false);
3796        };
3797        WhileStatement.prototype.typeCheck = function (typeFlow) {
3798            return typeFlow.typeCheckWhile(this);
3799        };
3800        WhileStatement.prototype.addToControlFlow = function (context) {
3801            var loopHeader = context.current;
3802            var loopStart = new BasicBlock();
3803            var afterLoop = new BasicBlock();
3804            loopHeader.addSuccessor(loopStart);
3805            context.current = loopStart;
3806            context.addContent(this.cond);
3807            var condBlock = context.current;
3808            var targetInfo = null;
3809            if (this.body) {
3810                context.current = new BasicBlock();
3811                condBlock.addSuccessor(context.current);
3812                context.pushStatement(this, loopStart, afterLoop);
3813                context.walk(this.body, this);
3814                targetInfo = context.popStatement();
3815            }
3816            if (!(context.noContinuation)) {
3817                var loopEnd = context.current;
3818                loopEnd.addSuccessor(loopStart);
3819            }
3820            context.current = afterLoop;
3821            condBlock.addSuccessor(afterLoop);
3822            // TODO: check for while (true) and then only continue if afterLoop has predecessors
3823            context.noContinuation = false;
3824            context.walker.options.goChildren = false;
3825        };
3826        return WhileStatement;
3827    }(Statement));
3828    TypeScript.WhileStatement = WhileStatement;
3829    var DoWhileStatement = /** @class */ (function (_super) {
3830        __extends(DoWhileStatement, _super);
3831        function DoWhileStatement() {
3832            var _this = _super.call(this, NodeType.DoWhile) || this;
3833            _this.body = null;
3834            _this.whileAST = null;
3835            _this.cond = null;
3836            return _this;
3837        }
3838        DoWhileStatement.prototype.isLoop = function () { return true; };
3839        DoWhileStatement.prototype.emit = function (emitter, tokenId, startLine) {
3840            emitter.emitParensAndCommentsInPlace(this, true);
3841            emitter.recordSourceMappingStart(this);
3842            var temp = emitter.setInObjectLiteral(false);
3843            emitter.writeToOutput("do");
3844            emitter.emitJavascriptStatements(this.body, true, false);
3845            emitter.recordSourceMappingStart(this.whileAST);
3846            emitter.writeToOutput("while");
3847            emitter.recordSourceMappingEnd(this.whileAST);
3848            emitter.writeToOutput('(');
3849            emitter.emitJavascript(this.cond, TokenID.CloseParen, false);
3850            emitter.writeToOutput(")");
3851            emitter.setInObjectLiteral(temp);
3852            emitter.recordSourceMappingEnd(this);
3853            emitter.emitParensAndCommentsInPlace(this, false);
3854        };
3855        DoWhileStatement.prototype.typeCheck = function (typeFlow) {
3856            return typeFlow.typeCheckDoWhile(this);
3857        };
3858        DoWhileStatement.prototype.addToControlFlow = function (context) {
3859            var loopHeader = context.current;
3860            var loopStart = new BasicBlock();
3861            var afterLoop = new BasicBlock();
3862            loopHeader.addSuccessor(loopStart);
3863            context.current = loopStart;
3864            var targetInfo = null;
3865            if (this.body) {
3866                context.pushStatement(this, loopStart, afterLoop);
3867                context.walk(this.body, this);
3868                targetInfo = context.popStatement();
3869            }
3870            if (!(context.noContinuation)) {
3871                var loopEnd = context.current;
3872                loopEnd.addSuccessor(loopStart);
3873                context.addContent(this.cond);
3874                // TODO: check for while (true)
3875                context.current = afterLoop;
3876                loopEnd.addSuccessor(afterLoop);
3877            }
3878            else {
3879                context.addUnreachable(this.cond);
3880            }
3881            context.walker.options.goChildren = false;
3882        };
3883        return DoWhileStatement;
3884    }(Statement));
3885    TypeScript.DoWhileStatement = DoWhileStatement;
3886    var IfStatement = /** @class */ (function (_super) {
3887        __extends(IfStatement, _super);
3888        function IfStatement(cond) {
3889            var _this = _super.call(this, NodeType.If) || this;
3890            _this.cond = cond;
3891            _this.elseBod = null;
3892            _this.statement = new ASTSpan();
3893            return _this;
3894        }
3895        IfStatement.prototype.isCompoundStatement = function () { return true; };
3896        IfStatement.prototype.emit = function (emitter, tokenId, startLine) {
3897            emitter.emitParensAndCommentsInPlace(this, true);
3898            emitter.recordSourceMappingStart(this);
3899            var temp = emitter.setInObjectLiteral(false);
3900            emitter.recordSourceMappingStart(this.statement);
3901            emitter.writeToOutput("if(");
3902            emitter.emitJavascript(this.cond, TokenID.If, false);
3903            emitter.writeToOutput(")");
3904            emitter.recordSourceMappingEnd(this.statement);
3905            emitter.emitJavascriptStatements(this.thenBod, true, false);
3906            if (this.elseBod) {
3907                emitter.writeToOutput(" else");
3908                emitter.emitJavascriptStatements(this.elseBod, true, true);
3909            }
3910            emitter.setInObjectLiteral(temp);
3911            emitter.recordSourceMappingEnd(this);
3912            emitter.emitParensAndCommentsInPlace(this, false);
3913        };
3914        IfStatement.prototype.typeCheck = function (typeFlow) {
3915            return typeFlow.typeCheckIf(this);
3916        };
3917        IfStatement.prototype.addToControlFlow = function (context) {
3918            this.cond.addToControlFlow(context);
3919            var afterIf = new BasicBlock();
3920            var beforeIf = context.current;
3921            context.pushStatement(this, beforeIf, afterIf);
3922            var hasContinuation = false;
3923            context.current = new BasicBlock();
3924            beforeIf.addSuccessor(context.current);
3925            context.walk(this.thenBod, this);
3926            if (!context.noContinuation) {
3927                hasContinuation = true;
3928                context.current.addSuccessor(afterIf);
3929            }
3930            if (this.elseBod) {
3931                // current block will be thenBod
3932                context.current = new BasicBlock();
3933                context.noContinuation = false;
3934                beforeIf.addSuccessor(context.current);
3935                context.walk(this.elseBod, this);
3936                if (!context.noContinuation) {
3937                    hasContinuation = true;
3938                    context.current.addSuccessor(afterIf);
3939                }
3940                else {
3941                    // thenBod created continuation for if statement
3942                    if (hasContinuation) {
3943                        context.noContinuation = false;
3944                    }
3945                }
3946            }
3947            else {
3948                beforeIf.addSuccessor(afterIf);
3949                context.noContinuation = false;
3950                hasContinuation = true;
3951            }
3952            var targetInfo = context.popStatement();
3953            if (afterIf.predecessors.length > 0) {
3954                context.noContinuation = false;
3955                hasContinuation = true;
3956            }
3957            if (hasContinuation) {
3958                context.current = afterIf;
3959            }
3960            context.walker.options.goChildren = false;
3961        };
3962        return IfStatement;
3963    }(Statement));
3964    TypeScript.IfStatement = IfStatement;
3965    var ReturnStatement = /** @class */ (function (_super) {
3966        __extends(ReturnStatement, _super);
3967        function ReturnStatement() {
3968            var _this = _super.call(this, NodeType.Return) || this;
3969            _this.returnExpression = null;
3970            return _this;
3971        }
3972        ReturnStatement.prototype.emit = function (emitter, tokenId, startLine) {
3973            emitter.emitParensAndCommentsInPlace(this, true);
3974            emitter.recordSourceMappingStart(this);
3975            var temp = emitter.setInObjectLiteral(false);
3976            if (this.returnExpression) {
3977                emitter.writeToOutput("return ");
3978                emitter.emitJavascript(this.returnExpression, TokenID.Semicolon, false);
3979            }
3980            else {
3981                emitter.writeToOutput("return;");
3982            }
3983            emitter.setInObjectLiteral(temp);
3984            emitter.recordSourceMappingEnd(this);
3985            emitter.emitParensAndCommentsInPlace(this, false);
3986        };
3987        ReturnStatement.prototype.addToControlFlow = function (context) {
3988            _super.prototype.addToControlFlow.call(this, context);
3989            context.returnStmt();
3990        };
3991        ReturnStatement.prototype.typeCheck = function (typeFlow) {
3992            return typeFlow.typeCheckReturn(this);
3993        };
3994        return ReturnStatement;
3995    }(Statement));
3996    TypeScript.ReturnStatement = ReturnStatement;
3997    var EndCode = /** @class */ (function (_super) {
3998        __extends(EndCode, _super);
3999        function EndCode() {
4000            return _super.call(this, NodeType.EndCode) || this;
4001        }
4002        return EndCode;
4003    }(AST));
4004    TypeScript.EndCode = EndCode;
4005    var ForInStatement = /** @class */ (function (_super) {
4006        __extends(ForInStatement, _super);
4007        function ForInStatement(lval, obj) {
4008            var _this = _super.call(this, NodeType.ForIn) || this;
4009            _this.lval = lval;
4010            _this.obj = obj;
4011            _this.statement = new ASTSpan();
4012            if (_this.lval && (_this.lval.nodeType == NodeType.VarDecl)) {
4013                _this.lval.varFlags |= VarFlags.AutoInit;
4014            }
4015            return _this;
4016        }
4017        ForInStatement.prototype.isLoop = function () { return true; };
4018        ForInStatement.prototype.isFiltered = function () {
4019            if (this.body) {
4020                var singleItem = null;
4021                if (this.body.nodeType == NodeType.List) {
4022                    var stmts = this.body;
4023                    if (stmts.members.length == 1) {
4024                        singleItem = stmts.members[0];
4025                    }
4026                }
4027                else {
4028                    singleItem = this.body;
4029                }
4030                // match template for filtering 'own' properties from obj
4031                if (singleItem !== null) {
4032                    if (singleItem.nodeType == NodeType.Block) {
4033                        var block = singleItem;
4034                        if ((block.statements !== null) && (block.statements.members.length == 1)) {
4035                            singleItem = block.statements.members[0];
4036                        }
4037                    }
4038                    if (singleItem.nodeType == NodeType.If) {
4039                        var cond = singleItem.cond;
4040                        if (cond.nodeType == NodeType.Call) {
4041                            var target = cond.target;
4042                            if (target.nodeType == NodeType.Dot) {
4043                                var binex = target;
4044                                if ((binex.operand1.nodeType == NodeType.Name) &&
4045                                    (this.obj.nodeType == NodeType.Name) &&
4046                                    (binex.operand1.actualText == this.obj.actualText)) {
4047                                    var prop = binex.operand2;
4048                                    if (prop.actualText == "hasOwnProperty") {
4049                                        var args = cond.arguments;
4050                                        if ((args !== null) && (args.members.length == 1)) {
4051                                            var arg = args.members[0];
4052                                            if ((arg.nodeType == NodeType.Name) &&
4053                                                (this.lval.nodeType == NodeType.Name)) {
4054                                                if ((this.lval.actualText) == arg.actualText) {
4055                                                    return true;
4056                                                }
4057                                            }
4058                                        }
4059                                    }
4060                                }
4061                            }
4062                        }
4063                    }
4064                }
4065            }
4066            return false;
4067        };
4068        ForInStatement.prototype.emit = function (emitter, tokenId, startLine) {
4069            emitter.emitParensAndCommentsInPlace(this, true);
4070            emitter.recordSourceMappingStart(this);
4071            var temp = emitter.setInObjectLiteral(false);
4072            emitter.recordSourceMappingStart(this.statement);
4073            emitter.writeToOutput("for(");
4074            emitter.emitJavascript(this.lval, TokenID.For, false);
4075            emitter.writeToOutput(" in ");
4076            emitter.emitJavascript(this.obj, TokenID.For, false);
4077            emitter.writeToOutput(")");
4078            emitter.recordSourceMappingEnd(this.statement);
4079            emitter.emitJavascriptStatements(this.body, true, false);
4080            emitter.setInObjectLiteral(temp);
4081            emitter.recordSourceMappingEnd(this);
4082            emitter.emitParensAndCommentsInPlace(this, false);
4083        };
4084        ForInStatement.prototype.typeCheck = function (typeFlow) {
4085            if (typeFlow.checker.styleSettings.forin) {
4086                if (!this.isFiltered()) {
4087                    typeFlow.checker.errorReporter.styleError(this, "no hasOwnProperty filter");
4088                }
4089            }
4090            return typeFlow.typeCheckForIn(this);
4091        };
4092        ForInStatement.prototype.addToControlFlow = function (context) {
4093            if (this.lval) {
4094                context.addContent(this.lval);
4095            }
4096            if (this.obj) {
4097                context.addContent(this.obj);
4098            }
4099            var loopHeader = context.current;
4100            var loopStart = new BasicBlock();
4101            var afterLoop = new BasicBlock();
4102            loopHeader.addSuccessor(loopStart);
4103            context.current = loopStart;
4104            if (this.body) {
4105                context.pushStatement(this, loopStart, afterLoop);
4106                context.walk(this.body, this);
4107                context.popStatement();
4108            }
4109            if (!(context.noContinuation)) {
4110                var loopEnd = context.current;
4111                loopEnd.addSuccessor(loopStart);
4112            }
4113            context.current = afterLoop;
4114            context.noContinuation = false;
4115            loopHeader.addSuccessor(afterLoop);
4116            context.walker.options.goChildren = false;
4117        };
4118        return ForInStatement;
4119    }(Statement));
4120    TypeScript.ForInStatement = ForInStatement;
4121    var ForStatement = /** @class */ (function (_super) {
4122        __extends(ForStatement, _super);
4123        function ForStatement(init) {
4124            var _this = _super.call(this, NodeType.For) || this;
4125            _this.init = init;
4126            return _this;
4127        }
4128        ForStatement.prototype.isLoop = function () { return true; };
4129        ForStatement.prototype.emit = function (emitter, tokenId, startLine) {
4130            emitter.emitParensAndCommentsInPlace(this, true);
4131            emitter.recordSourceMappingStart(this);
4132            var temp = emitter.setInObjectLiteral(false);
4133            emitter.writeToOutput("for(");
4134            if (this.init) {
4135                if (this.init.nodeType != NodeType.List) {
4136                    emitter.emitJavascript(this.init, TokenID.For, false);
4137                }
4138                else {
4139                    emitter.setInVarBlock(this.init.members.length);
4140                    emitter.emitJavascriptList(this.init, null, TokenID.For, false, false, false);
4141                }
4142            }
4143            emitter.writeToOutput("; ");
4144            emitter.emitJavascript(this.cond, TokenID.For, false);
4145            emitter.writeToOutput("; ");
4146            emitter.emitJavascript(this.incr, TokenID.For, false);
4147            emitter.writeToOutput(")");
4148            emitter.emitJavascriptStatements(this.body, true, false);
4149            emitter.setInObjectLiteral(temp);
4150            emitter.recordSourceMappingEnd(this);
4151            emitter.emitParensAndCommentsInPlace(this, false);
4152        };
4153        ForStatement.prototype.typeCheck = function (typeFlow) {
4154            return typeFlow.typeCheckFor(this);
4155        };
4156        ForStatement.prototype.addToControlFlow = function (context) {
4157            if (this.init) {
4158                context.addContent(this.init);
4159            }
4160            var loopHeader = context.current;
4161            var loopStart = new BasicBlock();
4162            var afterLoop = new BasicBlock();
4163            loopHeader.addSuccessor(loopStart);
4164            context.current = loopStart;
4165            var condBlock = null;
4166            var continueTarget = loopStart;
4167            var incrBB = null;
4168            if (this.incr) {
4169                incrBB = new BasicBlock();
4170                continueTarget = incrBB;
4171            }
4172            if (this.cond) {
4173                condBlock = context.current;
4174                context.addContent(this.cond);
4175                context.current = new BasicBlock();
4176                condBlock.addSuccessor(context.current);
4177            }
4178            var targetInfo = null;
4179            if (this.body) {
4180                context.pushStatement(this, continueTarget, afterLoop);
4181                context.walk(this.body, this);
4182                targetInfo = context.popStatement();
4183            }
4184            if (this.incr) {
4185                if (context.noContinuation) {
4186                    if (incrBB.predecessors.length == 0) {
4187                        context.addUnreachable(this.incr);
4188                    }
4189                }
4190                else {
4191                    context.current.addSuccessor(incrBB);
4192                    context.current = incrBB;
4193                    context.addContent(this.incr);
4194                }
4195            }
4196            var loopEnd = context.current;
4197            if (!(context.noContinuation)) {
4198                loopEnd.addSuccessor(loopStart);
4199            }
4200            if (condBlock) {
4201                condBlock.addSuccessor(afterLoop);
4202                context.noContinuation = false;
4203            }
4204            if (afterLoop.predecessors.length > 0) {
4205                context.noContinuation = false;
4206                context.current = afterLoop;
4207            }
4208            context.walker.options.goChildren = false;
4209        };
4210        return ForStatement;
4211    }(Statement));
4212    TypeScript.ForStatement = ForStatement;
4213    var WithStatement = /** @class */ (function (_super) {
4214        __extends(WithStatement, _super);
4215        function WithStatement(expr) {
4216            var _this = _super.call(this, NodeType.With) || this;
4217            _this.expr = expr;
4218            _this.withSym = null;
4219            return _this;
4220        }
4221        WithStatement.prototype.isCompoundStatement = function () { return true; };
4222        WithStatement.prototype.emit = function (emitter, tokenId, startLine) {
4223            emitter.emitParensAndCommentsInPlace(this, true);
4224            emitter.recordSourceMappingStart(this);
4225            emitter.writeToOutput("with (");
4226            if (this.expr) {
4227                emitter.emitJavascript(this.expr, TokenID.With, false);
4228            }
4229            emitter.writeToOutput(")");
4230            emitter.emitJavascriptStatements(this.body, true, false);
4231            emitter.recordSourceMappingEnd(this);
4232            emitter.emitParensAndCommentsInPlace(this, false);
4233        };
4234        WithStatement.prototype.typeCheck = function (typeFlow) {
4235            return typeFlow.typeCheckWith(this);
4236        };
4237        return WithStatement;
4238    }(Statement));
4239    TypeScript.WithStatement = WithStatement;
4240    var SwitchStatement = /** @class */ (function (_super) {
4241        __extends(SwitchStatement, _super);
4242        function SwitchStatement(val) {
4243            var _this = _super.call(this, NodeType.Switch) || this;
4244            _this.val = val;
4245            _this.defaultCase = null;
4246            _this.statement = new ASTSpan();
4247            return _this;
4248        }
4249        SwitchStatement.prototype.isCompoundStatement = function () { return true; };
4250        SwitchStatement.prototype.emit = function (emitter, tokenId, startLine) {
4251            emitter.emitParensAndCommentsInPlace(this, true);
4252            emitter.recordSourceMappingStart(this);
4253            var temp = emitter.setInObjectLiteral(false);
4254            emitter.recordSourceMappingStart(this.statement);
4255            emitter.writeToOutput("switch(");
4256            emitter.emitJavascript(this.val, TokenID.Identifier, false);
4257            emitter.writeToOutput(")");
4258            emitter.recordSourceMappingEnd(this.statement);
4259            emitter.writeLineToOutput(" {");
4260            emitter.indenter.increaseIndent();
4261            var casesLen = this.caseList.members.length;
4262            for (var i = 0; i < casesLen; i++) {
4263                var caseExpr = this.caseList.members[i];
4264                emitter.emitJavascript(caseExpr, TokenID.Case, true);
4265                emitter.writeLineToOutput("");
4266            }
4267            emitter.indenter.decreaseIndent();
4268            emitter.emitIndent();
4269            emitter.writeToOutput("}");
4270            emitter.setInObjectLiteral(temp);
4271            emitter.recordSourceMappingEnd(this);
4272            emitter.emitParensAndCommentsInPlace(this, false);
4273        };
4274        SwitchStatement.prototype.typeCheck = function (typeFlow) {
4275            var len = this.caseList.members.length;
4276            this.val = typeFlow.typeCheck(this.val);
4277            for (var i = 0; i < len; i++) {
4278                this.caseList.members[i] = typeFlow.typeCheck(this.caseList.members[i]);
4279            }
4280            this.defaultCase = typeFlow.typeCheck(this.defaultCase);
4281            this.type = typeFlow.voidType;
4282            return this;
4283        };
4284        // if there are break statements that match this switch, then just link cond block with block after switch
4285        SwitchStatement.prototype.addToControlFlow = function (context) {
4286            var condBlock = context.current;
4287            context.addContent(this.val);
4288            var execBlock = new BasicBlock();
4289            var afterSwitch = new BasicBlock();
4290            condBlock.addSuccessor(execBlock);
4291            context.pushSwitch(execBlock);
4292            context.current = execBlock;
4293            context.pushStatement(this, execBlock, afterSwitch);
4294            context.walk(this.caseList, this);
4295            context.popSwitch();
4296            var targetInfo = context.popStatement();
4297            var hasCondContinuation = (this.defaultCase == null);
4298            if (this.defaultCase == null) {
4299                condBlock.addSuccessor(afterSwitch);
4300            }
4301            if (afterSwitch.predecessors.length > 0) {
4302                context.noContinuation = false;
4303                context.current = afterSwitch;
4304            }
4305            else {
4306                context.noContinuation = true;
4307            }
4308            context.walker.options.goChildren = false;
4309        };
4310        return SwitchStatement;
4311    }(Statement));
4312    TypeScript.SwitchStatement = SwitchStatement;
4313    var CaseStatement = /** @class */ (function (_super) {
4314        __extends(CaseStatement, _super);
4315        function CaseStatement() {
4316            var _this = _super.call(this, NodeType.Case) || this;
4317            _this.expr = null;
4318            return _this;
4319        }
4320        CaseStatement.prototype.emit = function (emitter, tokenId, startLine) {
4321            emitter.emitParensAndCommentsInPlace(this, true);
4322            emitter.recordSourceMappingStart(this);
4323            if (this.expr) {
4324                emitter.writeToOutput("case ");
4325                emitter.emitJavascript(this.expr, TokenID.Identifier, false);
4326            }
4327            else {
4328                emitter.writeToOutput("default");
4329            }
4330            emitter.writeToOutput(":");
4331            emitter.emitJavascriptStatements(this.body, false, false);
4332            emitter.recordSourceMappingEnd(this);
4333            emitter.emitParensAndCommentsInPlace(this, false);
4334        };
4335        CaseStatement.prototype.typeCheck = function (typeFlow) {
4336            this.expr = typeFlow.typeCheck(this.expr);
4337            typeFlow.typeCheck(this.body);
4338            this.type = typeFlow.voidType;
4339            return this;
4340        };
4341        // TODO: more reasoning about unreachable cases (such as duplicate literals as case expressions)
4342        // for now, assume all cases are reachable, regardless of whether some cases fall through
4343        CaseStatement.prototype.addToControlFlow = function (context) {
4344            var execBlock = new BasicBlock();
4345            var sw = context.currentSwitch[context.currentSwitch.length - 1];
4346            // TODO: fall-through from previous (+ to end of switch)
4347            if (this.expr) {
4348                var exprBlock = new BasicBlock();
4349                context.current = exprBlock;
4350                sw.addSuccessor(exprBlock);
4351                context.addContent(this.expr);
4352                exprBlock.addSuccessor(execBlock);
4353            }
4354            else {
4355                sw.addSuccessor(execBlock);
4356            }
4357            context.current = execBlock;
4358            if (this.body) {
4359                context.walk(this.body, this);
4360            }
4361            context.noContinuation = false;
4362            context.walker.options.goChildren = false;
4363        };
4364        return CaseStatement;
4365    }(Statement));
4366    TypeScript.CaseStatement = CaseStatement;
4367    var TypeReference = /** @class */ (function (_super) {
4368        __extends(TypeReference, _super);
4369        function TypeReference(term, arrayCount) {
4370            var _this = _super.call(this, NodeType.TypeRef) || this;
4371            _this.term = term;
4372            _this.arrayCount = arrayCount;
4373            return _this;
4374        }
4375        TypeReference.prototype.emit = function (emitter, tokenId, startLine) {
4376            throw new Error("should not emit a type ref");
4377        };
4378        TypeReference.prototype.typeCheck = function (typeFlow) {
4379            var prevInTCTR = typeFlow.inTypeRefTypeCheck;
4380            typeFlow.inTypeRefTypeCheck = true;
4381            var typeLink = getTypeLink(this, typeFlow.checker, true);
4382            typeFlow.checker.resolveTypeLink(typeFlow.scope, typeLink, false);
4383            if (this.term) {
4384                typeFlow.typeCheck(this.term);
4385            }
4386            typeFlow.checkForVoidConstructor(typeLink.type, this);
4387            this.type = typeLink.type;
4388            // in error recovery cases, there may not be a term
4389            if (this.term) {
4390                this.term.type = this.type;
4391            }
4392            typeFlow.inTypeRefTypeCheck = prevInTCTR;
4393            return this;
4394        };
4395        return TypeReference;
4396    }(AST));
4397    TypeScript.TypeReference = TypeReference;
4398    var TryFinally = /** @class */ (function (_super) {
4399        __extends(TryFinally, _super);
4400        function TryFinally(tryNode, finallyNode) {
4401            var _this = _super.call(this, NodeType.TryFinally) || this;
4402            _this.tryNode = tryNode;
4403            _this.finallyNode = finallyNode;
4404            return _this;
4405        }
4406        TryFinally.prototype.isCompoundStatement = function () { return true; };
4407        TryFinally.prototype.emit = function (emitter, tokenId, startLine) {
4408            emitter.recordSourceMappingStart(this);
4409            emitter.emitJavascript(this.tryNode, TokenID.Try, false);
4410            emitter.emitJavascript(this.finallyNode, TokenID.Finally, false);
4411            emitter.recordSourceMappingEnd(this);
4412        };
4413        TryFinally.prototype.typeCheck = function (typeFlow) {
4414            this.tryNode = typeFlow.typeCheck(this.tryNode);
4415            this.finallyNode = typeFlow.typeCheck(this.finallyNode);
4416            this.type = typeFlow.voidType;
4417            return this;
4418        };
4419        TryFinally.prototype.addToControlFlow = function (context) {
4420            var afterFinally = new BasicBlock();
4421            context.walk(this.tryNode, this);
4422            var finBlock = new BasicBlock();
4423            if (context.current) {
4424                context.current.addSuccessor(finBlock);
4425            }
4426            context.current = finBlock;
4427            context.pushStatement(this, null, afterFinally);
4428            context.walk(this.finallyNode, this);
4429            if (!context.noContinuation && context.current) {
4430                context.current.addSuccessor(afterFinally);
4431            }
4432            if (afterFinally.predecessors.length > 0) {
4433                context.current = afterFinally;
4434            }
4435            else {
4436                context.noContinuation = true;
4437            }
4438            context.popStatement();
4439            context.walker.options.goChildren = false;
4440        };
4441        return TryFinally;
4442    }(Statement));
4443    TypeScript.TryFinally = TryFinally;
4444    var TryCatch = /** @class */ (function (_super) {
4445        __extends(TryCatch, _super);
4446        function TryCatch(tryNode, catchNode) {
4447            var _this = _super.call(this, NodeType.TryCatch) || this;
4448            _this.tryNode = tryNode;
4449            _this.catchNode = catchNode;
4450            return _this;
4451        }
4452        TryCatch.prototype.isCompoundStatement = function () { return true; };
4453        TryCatch.prototype.emit = function (emitter, tokenId, startLine) {
4454            emitter.emitParensAndCommentsInPlace(this, true);
4455            emitter.recordSourceMappingStart(this);
4456            emitter.emitJavascript(this.tryNode, TokenID.Try, false);
4457            emitter.emitJavascript(this.catchNode, TokenID.Catch, false);
4458            emitter.recordSourceMappingEnd(this);
4459            emitter.emitParensAndCommentsInPlace(this, false);
4460        };
4461        TryCatch.prototype.addToControlFlow = function (context) {
4462            var beforeTry = context.current;
4463            var tryBlock = new BasicBlock();
4464            beforeTry.addSuccessor(tryBlock);
4465            context.current = tryBlock;
4466            var afterTryCatch = new BasicBlock();
4467            context.pushStatement(this, null, afterTryCatch);
4468            context.walk(this.tryNode, this);
4469            if (!context.noContinuation) {
4470                if (context.current) {
4471                    context.current.addSuccessor(afterTryCatch);
4472                }
4473            }
4474            context.current = new BasicBlock();
4475            beforeTry.addSuccessor(context.current);
4476            context.walk(this.catchNode, this);
4477            context.popStatement();
4478            if (!context.noContinuation) {
4479                if (context.current) {
4480                    context.current.addSuccessor(afterTryCatch);
4481                }
4482            }
4483            context.current = afterTryCatch;
4484            context.walker.options.goChildren = false;
4485        };
4486        TryCatch.prototype.typeCheck = function (typeFlow) {
4487            this.tryNode = typeFlow.typeCheck(this.tryNode);
4488            this.catchNode = typeFlow.typeCheck(this.catchNode);
4489            this.type = typeFlow.voidType;
4490            return this;
4491        };
4492        return TryCatch;
4493    }(Statement));
4494    TypeScript.TryCatch = TryCatch;
4495    var Try = /** @class */ (function (_super) {
4496        __extends(Try, _super);
4497        function Try(body) {
4498            var _this = _super.call(this, NodeType.Try) || this;
4499            _this.body = body;
4500            return _this;
4501        }
4502        Try.prototype.emit = function (emitter, tokenId, startLine) {
4503            emitter.emitParensAndCommentsInPlace(this, true);
4504            emitter.recordSourceMappingStart(this);
4505            emitter.writeToOutput("try ");
4506            emitter.emitJavascript(this.body, TokenID.Try, false);
4507            emitter.recordSourceMappingEnd(this);
4508            emitter.emitParensAndCommentsInPlace(this, false);
4509        };
4510        Try.prototype.typeCheck = function (typeFlow) {
4511            this.body = typeFlow.typeCheck(this.body);
4512            return this;
4513        };
4514        Try.prototype.addToControlFlow = function (context) {
4515            if (this.body) {
4516                context.walk(this.body, this);
4517            }
4518            context.walker.options.goChildren = false;
4519            context.noContinuation = false;
4520        };
4521        return Try;
4522    }(Statement));
4523    TypeScript.Try = Try;
4524    var Catch = /** @class */ (function (_super) {
4525        __extends(Catch, _super);
4526        function Catch(param, body) {
4527            var _this = _super.call(this, NodeType.Catch) || this;
4528            _this.param = param;
4529            _this.body = body;
4530            _this.statement = new ASTSpan();
4531            _this.containedScope = null;
4532            if (_this.param) {
4533                _this.param.varFlags |= VarFlags.AutoInit;
4534            }
4535            return _this;
4536        }
4537        Catch.prototype.emit = function (emitter, tokenId, startLine) {
4538            emitter.emitParensAndCommentsInPlace(this, true);
4539            emitter.recordSourceMappingStart(this);
4540            emitter.writeToOutput(" ");
4541            emitter.recordSourceMappingStart(this.statement);
4542            emitter.writeToOutput("catch (");
4543            emitter.emitJavascript(this.param, TokenID.OpenParen, false);
4544            emitter.writeToOutput(")");
4545            emitter.recordSourceMappingEnd(this.statement);
4546            emitter.emitJavascript(this.body, TokenID.Catch, false);
4547            emitter.recordSourceMappingEnd(this);
4548            emitter.emitParensAndCommentsInPlace(this, false);
4549        };
4550        Catch.prototype.addToControlFlow = function (context) {
4551            if (this.param) {
4552                context.addContent(this.param);
4553                var bodBlock = new BasicBlock();
4554                context.current.addSuccessor(bodBlock);
4555                context.current = bodBlock;
4556            }
4557            if (this.body) {
4558                context.walk(this.body, this);
4559            }
4560            context.noContinuation = false;
4561            context.walker.options.goChildren = false;
4562        };
4563        Catch.prototype.typeCheck = function (typeFlow) {
4564            var prevScope = typeFlow.scope;
4565            typeFlow.scope = this.containedScope;
4566            this.param = typeFlow.typeCheck(this.param);
4567            var exceptVar = new ValueLocation();
4568            var varSym = new VariableSymbol(this.param.id.text, this.param.minChar, typeFlow.checker.locationInfo.unitIndex, exceptVar);
4569            exceptVar.symbol = varSym;
4570            exceptVar.typeLink = new TypeLink();
4571            // var type for now (add syntax for type annotation)
4572            exceptVar.typeLink.type = typeFlow.anyType;
4573            var thisFnc = typeFlow.thisFnc;
4574            if (thisFnc && thisFnc.type) {
4575                exceptVar.symbol.container = thisFnc.type.symbol;
4576            }
4577            else {
4578                exceptVar.symbol.container = null;
4579            }
4580            this.param.sym = exceptVar.symbol;
4581            typeFlow.scope.enter(exceptVar.symbol.container, this.param, exceptVar.symbol, typeFlow.checker.errorReporter, false, false, false);
4582            this.body = typeFlow.typeCheck(this.body);
4583            // if we're in provisional typecheck mode, clean up the symbol entry
4584            // REVIEW: This is obviously bad form, since we're counting on the internal
4585            // layout of the symbol table, but this is also the only place where we insert
4586            // symbols during typecheck
4587            if (typeFlow.checker.inProvisionalTypecheckMode()) {
4588                var table = typeFlow.scope.getTable();
4589                table.secondaryTable.table[exceptVar.symbol.name] = undefined;
4590            }
4591            this.type = typeFlow.voidType;
4592            typeFlow.scope = prevScope;
4593            return this;
4594        };
4595        return Catch;
4596    }(Statement));
4597    TypeScript.Catch = Catch;
4598    var Finally = /** @class */ (function (_super) {
4599        __extends(Finally, _super);
4600        function Finally(body) {
4601            var _this = _super.call(this, NodeType.Finally) || this;
4602            _this.body = body;
4603            return _this;
4604        }
4605        Finally.prototype.emit = function (emitter, tokenId, startLine) {
4606            emitter.emitParensAndCommentsInPlace(this, true);
4607            emitter.recordSourceMappingStart(this);
4608            emitter.writeToOutput("finally");
4609            emitter.emitJavascript(this.body, TokenID.Finally, false);
4610            emitter.recordSourceMappingEnd(this);
4611            emitter.emitParensAndCommentsInPlace(this, false);
4612        };
4613        Finally.prototype.addToControlFlow = function (context) {
4614            if (this.body) {
4615                context.walk(this.body, this);
4616            }
4617            context.walker.options.goChildren = false;
4618            context.noContinuation = false;
4619        };
4620        Finally.prototype.typeCheck = function (typeFlow) {
4621            this.body = typeFlow.typeCheck(this.body);
4622            return this;
4623        };
4624        return Finally;
4625    }(Statement));
4626    TypeScript.Finally = Finally;
4627    var Comment = /** @class */ (function (_super) {
4628        __extends(Comment, _super);
4629        function Comment(content, isBlockComment, endsLine) {
4630            var _this = _super.call(this, NodeType.Comment) || this;
4631            _this.content = content;
4632            _this.isBlockComment = isBlockComment;
4633            _this.endsLine = endsLine;
4634            _this.text = null;
4635            return _this;
4636        }
4637        Comment.prototype.getText = function () {
4638            if (this.text == null) {
4639                if (this.isBlockComment) {
4640                    this.text = this.content.split("\n");
4641                    for (var i = 0; i < this.text.length; i++) {
4642                        this.text[i] = this.text[i].replace(/^\s+|\s+$/g, '');
4643                    }
4644                }
4645                else {
4646                    this.text = [(this.content.replace(/^\s+|\s+$/g, ''))];
4647                }
4648            }
4649            return this.text;
4650        };
4651        return Comment;
4652    }(AST));
4653    TypeScript.Comment = Comment;
4654    var DebuggerStatement = /** @class */ (function (_super) {
4655        __extends(DebuggerStatement, _super);
4656        function DebuggerStatement() {
4657            return _super.call(this, NodeType.Debugger) || this;
4658        }
4659        DebuggerStatement.prototype.emit = function (emitter, tokenId, startLine) {
4660            emitter.emitParensAndCommentsInPlace(this, true);
4661            emitter.recordSourceMappingStart(this);
4662            emitter.writeLineToOutput("debugger;");
4663            emitter.recordSourceMappingEnd(this);
4664            emitter.emitParensAndCommentsInPlace(this, false);
4665        };
4666        return DebuggerStatement;
4667    }(Statement));
4668    TypeScript.DebuggerStatement = DebuggerStatement;
4669})(TypeScript || (TypeScript = {}));
4670