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